openapi: 3.0.0
info:
  title: PeerTube
  version: 4.0.0
  contact:
    name: PeerTube Community
    url: https://joinpeertube.org
  license:
    name: AGPLv3.0
    url: https://github.com/Chocobozzz/PeerTube/blob/master/LICENSE
  x-logo:
    url: https://joinpeertube.org/img/brand.png
    altText: PeerTube Project Homepage
  description: |
    The PeerTube API is built on HTTP(S) and is RESTful. You can use your favorite
    HTTP/REST library for your programming language to use PeerTube. The spec API is fully compatible with
    [openapi-generator](https://github.com/OpenAPITools/openapi-generator/wiki/API-client-generator-HOWTO)
    which generates a client SDK in the language of your choice - we generate some client SDKs automatically:

    - [Python](https://framagit.org/framasoft/peertube/clients/python)
    - [Go](https://framagit.org/framasoft/peertube/clients/go)
    - [Kotlin](https://framagit.org/framasoft/peertube/clients/kotlin)

    See the [REST API quick start](https://docs.joinpeertube.org/api-rest-getting-started) for a few
    examples of using the PeerTube API.

    # Authentication

    When you sign up for an account on a PeerTube instance, you are given the possibility
    to generate sessions on it, and authenticate there using an access token. Only __one
    access token can currently be used at a time__.

    ## Roles

    Accounts are given permissions based on their role. There are three roles on
    PeerTube: Administrator, Moderator, and User. See the [roles guide](https://docs.joinpeertube.org/admin-managing-users?id=roles) for a detail of their permissions.

    # Errors

    The API uses standard HTTP status codes to indicate the success or failure
    of the API call, completed by a [RFC7807-compliant](https://tools.ietf.org/html/rfc7807) response body.

    ```
    HTTP 1.1 404 Not Found
    Content-Type: application/problem+json; charset=utf-8

    {
      "detail": "Video not found",
      "docs": "https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo",
      "status": 404,
      "title": "Not Found",
      "type": "about:blank"
    }
    ```

    We provide error `type` values for [a growing number of cases](https://github.com/Chocobozzz/PeerTube/blob/develop/shared/models/server/server-error-code.enum.ts),
    but it is still optional. Types are used to disambiguate errors that bear the same status code
    and are non-obvious:

    ```
    HTTP 1.1 403 Forbidden
    Content-Type: application/problem+json; charset=utf-8

    {
      "detail": "Cannot get this video regarding follow constraints",
      "docs": "https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo",
      "status": 403,
      "title": "Forbidden",
      "type": "https://docs.joinpeertube.org/api-rest-reference.html#section/Errors/does_not_respect_follow_constraints"
    }
    ```

    Here a 403 error could otherwise mean that the video is private or blocklisted.

    ### Validation errors

    Each parameter is evaluated on its own against a set of rules before the route validator
    proceeds with potential testing involving parameter combinations. Errors coming from validation
    errors appear earlier and benefit from a more detailed error description:

    ```
    HTTP 1.1 400 Bad Request
    Content-Type: application/problem+json; charset=utf-8

    {
      "detail": "Incorrect request parameters: id",
      "docs": "https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo",
      "instance": "/api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180",
      "invalid-params": {
        "id": {
          "location": "params",
          "msg": "Invalid value",
          "param": "id",
          "value": "9c9de5e8-0a1e-484a-b099-e80766180"
        }
      },
      "status": 400,
      "title": "Bad Request",
      "type": "about:blank"
    }
    ```

    Where `id` is the name of the field concerned by the error, within the route definition.
    `invalid-params.<field>.location` can be either 'params', 'body', 'header', 'query' or 'cookies', and
    `invalid-params.<field>.value` reports the value that didn't pass validation whose `invalid-params.<field>.msg`
    is about.

    ### Deprecated error fields

    Some fields could be included with previous versions. They are still included but their use is deprecated:
    - `error`: superseded by `detail`
    - `code`: superseded by `type` (which is now an URI)

    # Rate limits

    We are rate-limiting all endpoints of PeerTube's API. Custom values can be set by administrators:

    | Endpoint (prefix: `/api/v1`) | Calls         | Time frame   |
    |------------------------------|---------------|--------------|
    | `/*`                         | 50            | 10 seconds   |
    | `POST /users/token`          | 15            | 5 minutes    |
    | `POST /users/register`       | 2<sup>*</sup> | 5 minutes    |
    | `POST /users/ask-send-verify-email` | 3      | 5 minutes    |

    Depending on the endpoint, <sup>*</sup>failed requests are not taken into account. A service
    limit is announced by a `429 Too Many Requests` status code.

    You can get details about the current state of your rate limit by reading the
    following headers:

    | Header                  | Description                                                |
    |-------------------------|------------------------------------------------------------|
    | `X-RateLimit-Limit`     | Number of max requests allowed in the current time period  |
    | `X-RateLimit-Remaining` | Number of remaining requests in the current time period    |
    | `X-RateLimit-Reset`     | Timestamp of end of current time period as UNIX timestamp  |
    | `Retry-After`           | Seconds to delay after the first `429` is received         |

    # CORS

    This API features [Cross-Origin Resource Sharing (CORS)](https://fetch.spec.whatwg.org/),
    allowing cross-domain communication from the browser for some routes:

    | Endpoint                    |
    |------------------------- ---|
    | `/api/*`                    |
    | `/download/*`               |
    | `/lazy-static/*`            |
    | `/live/segments-sha256/*`   |
    | `/.well-known/webfinger`    |

    In addition, all routes serving ActivityPub are CORS-enabled for all origins.
externalDocs:
  url: https://docs.joinpeertube.org/api-rest-reference.html
tags:
  - name: Register
    description: |
      As a visitor, you can use this API to open an account (if registrations are open on
      that PeerTube instance). As an admin, you should use the dedicated [User creation
      API](#operation/addUser) instead.
  - name: Session
    x-displayName: Login/Logout
    description: |
      Sessions deal with access tokens over time. Only __one session token can currently be used at a time__.
  - name: Accounts
    description: >
      Accounts encompass remote accounts discovered across the federation,
      and correspond to the main Actor, along with video channels a user can create, which
      are also Actors.

      When a comment is posted, it is done with your Account's Actor.
  - name: Users
    description: >
      Using some features of PeerTube require authentication, for which User
      provide different levels of permission as well as associated user
      information. Each user has a corresponding local Account for federation.
  - name: My User
    description: >
      Operations related to your own User, when logged-in.
  - name: My Subscriptions
    description: >
      Operations related to your subscriptions to video channels, their
      new videos, and how to keep up to date with their latest publications!
  - name: My History
    description: >
      Operations related to your watch history.
  - name: My Notifications
    description: >
      Notifications following new videos, follows or reports. They allow you
      to keep track of the interactions and overall important information that
      concerns you. You MAY set per-notification type delivery preference, to
      receive the info either by mail, by in-browser notification or both.
  - name: Config
    description: >
      Each server exposes public information regarding supported videos and
      options.
  - name: Job
    description: >
      Jobs are long-running tasks enqueued and processed by the instance
      itself. No additional worker registration is currently available.
  - name: Instance Follows
    description: >
      Managing servers which the instance interacts with is crucial to the
      concept of federation in PeerTube and external video indexation. The PeerTube
      server then deals with inter-server ActivityPub operations and propagates
      information across its social graph by posting activities to actors' inbox
      endpoints.
    externalDocs:
      url: https://docs.joinpeertube.org/admin-following-instances?id=instances-follows
  - name: Instance Redundancy
    description: >
      Redundancy is part of the inter-server solidarity that PeerTube fosters.
      Manage the list of instances you wish to help by seeding their videos according
      to the policy of video selection of your choice. Note that you have a similar functionality
      to mirror individual videos, see [video mirroring](#tag/Video-Mirroring).
    externalDocs:
      url: https://docs.joinpeertube.org/admin-following-instances?id=instances-redundancy
  - name: Plugins
    description: >
      Managing plugins installed from a local path or from NPM, or search for new ones.
    externalDocs:
      url: https://docs.joinpeertube.org/api-plugins
  - name: Abuses
    description: |
      Abuses deal with reports of local or remote videos/comments/accounts alike.
  - name: Video
    description: |
      Operations dealing with listing, uploading, fetching or modifying videos.
  - name: Video Upload
    description: |
      Operations dealing with adding video or audio. PeerTube supports two upload modes, and three import modes.

      ### Upload

      - [_legacy_](#operation/uploadLegacy), where the video file is sent in a single request
      - [_resumable_](#operation/uploadResumableInit), where the video file is sent in chunks

      You can upload videos more reliably by using the resumable variant. Its protocol lets
      you resume an upload operation after a network interruption or other transmission failure,
      saving time and bandwidth in the event of network failures.

      Favor using resumable uploads in any of the following cases:
      - You are transferring large files
      - The likelihood of a network interruption is high
      - Uploads are originating from a device with a low-bandwidth or unstable Internet connection,
        such as a mobile device

      ### Import

      - _URL_-based: where the URL points to any service supported by [youtube-dl](https://ytdl-org.github.io/youtube-dl/)
      - _magnet_-based: where the URI resolves to a BitTorrent ressource containing a single supported video file
      - _torrent_-based: where the metainfo file resolves to a BitTorrent ressource containing a single supported video file

      The import function is practical when the desired video/audio is available online. It makes PeerTube
      download it for you, saving you as much bandwidth and avoiding any instability or limitation your network might have.
  - name: Video Imports
    description: Operations dealing with listing, adding and removing video imports.
  - name: Video Captions
    description: Operations dealing with listing, adding and removing closed captions of a video.
  - name: Video Channels
    description: Operations dealing with the creation, modification and listing of videos within a channel.
  - name: Video Comments
    description: >
      Operations dealing with comments to a video. Comments are organized in threads: adding a
      comment in response to the video starts a thread, adding a reply to a comment adds it to
      its root comment thread.
  - name: Video Blocks
    description: Operations dealing with blocking videos (removing them from view and preventing interactions).
  - name: Video Rates
    description: Like/dislike a video.
  - name: Video Playlists
    description: Operations dealing with playlists of videos. Playlists are bound to users and/or channels.
  - name: Video Files
    description: Operations on video files
  - name: Video Transcoding
    description: Video transcoding related operations
  - name: Feeds
    description: Server syndication feeds
  - name: Search
    description: |
      The search helps to find _videos_ or _channels_ from within the instance and beyond.
      Videos from other instances federated by the instance (that is, instances
      followed by the instance) can be found via keywords and other criteria of
      the advanced search.

      Administrators can also enable the use of a remote search system, indexing
      videos and channels not could be not federated by the instance.
  - name: Homepage
    description: Get and update the custom homepage
  - name: Video Mirroring
    description: |
      PeerTube instances can mirror videos from one another, and help distribute some videos.

      For importing videos as your own, refer to [video imports](#operation/importVideo).
x-tagGroups:
  - name: Auth
    tags:
      - Register
      - Session
  - name: Accounts
    tags:
      - Accounts
      - Users
      - My User
      - My Subscriptions
      - My Notifications
      - My History
  - name: Videos
    tags:
      - Video
      - Video Upload
      - Video Imports
      - Video Captions
      - Video Channels
      - Video Comments
      - Video Rates
      - Video Playlists
      - Video Ownership Change
      - Video Mirroring
      - Video Files
      - Video Transcoding
      - Live Videos
      - Feeds
  - name: Search
    tags:
      - Search
  - name: Custom pages
    tags:
      - Homepage
  - name: Moderation
    tags:
      - Abuses
      - Video Blocks
      - Account Blocks
      - Server Blocks
  - name: Instance Configuration
    tags:
      - Config
      - Instance Follows
      - Instance Redundancy
      - Plugins
  - name: Jobs
    tags:
      - Job
paths:
  '/accounts/{name}':
    get:
      tags:
        - Accounts
      summary: Get an account
      operationId: getAccount
      parameters:
        - $ref: '#/components/parameters/name'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Account'
        '404':
          description: account not found

  '/accounts/{name}/videos':
    get:
      tags:
        - Accounts
        - Video
      summary: 'List videos of an account'
      operationId: getAccountVideos
      parameters:
        - $ref: '#/components/parameters/name'
        - $ref: '#/components/parameters/categoryOneOf'
        - $ref: '#/components/parameters/isLive'
        - $ref: '#/components/parameters/tagsOneOf'
        - $ref: '#/components/parameters/tagsAllOf'
        - $ref: '#/components/parameters/licenceOneOf'
        - $ref: '#/components/parameters/languageOneOf'
        - $ref: '#/components/parameters/nsfw'
        - $ref: '#/components/parameters/isLocal'
        - $ref: '#/components/parameters/include'
        - $ref: '#/components/parameters/privacyOneOf'
        - $ref: '#/components/parameters/hasHLSFiles'
        - $ref: '#/components/parameters/hasWebtorrentFiles'
        - $ref: '#/components/parameters/skipCount'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/videosSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoListResponse'
      x-codeSamples:
        - lang: JavaScript
          source: |
            fetch('https://peertube2.cpy.re/api/v1/accounts/{name}/videos')
            .then(function(response) {
              return response.json()
            }).then(function(data) {
              console.log(data)
            })
        - lang: Shell
          source: |
            ## DEPENDENCIES: jq
            curl -s https://peertube2.cpy.re/api/v1/accounts/{name}/videos | jq
        - lang: Ruby
          source: |
            require 'net/http'
            require 'json'

            uri = URI.parse("https://peertube2.cpy.re/api/v1/accounts/{name}/videos")

            http = Net::HTTP.new(uri.host, uri.port)
            http.use_ssl = true

            response = http.get(uri.request_uri)

            puts JSON.parse(response.read_body)
        - lang: Python
          source: |
            import requests

            r = requests.get("https://peertube2.cpy.re/api/v1//accounts/{name}/videos")
            json = r.json()

            print(json)

  '/accounts/{name}/followers':
    get:
      tags:
        - Accounts
      summary: 'List followers of an account'
      security:
        - OAuth2: []
      operationId: getAccountFollowers
      parameters:
        - $ref: '#/components/parameters/name'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/followersSort'
        - $ref: '#/components/parameters/search'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Follow'

  /accounts:
    get:
      tags:
        - Accounts
      summary: List accounts
      operationId: getAccounts
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            'application/json':
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Account'

  /config:
    get:
      tags:
        - Config
      summary: Get instance public configuration
      operationId: getConfig
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServerConfig'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/api/v1/config

  /config/about:
    get:
      summary: Get instance "About" information
      operationId: getAbout
      tags:
        - Config
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServerConfigAbout'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/api/v1/config/about

  /config/custom:
    get:
      summary: Get instance runtime configuration
      operationId: getCustomConfig
      tags:
        - Config
      security:
        - OAuth2:
          - admin
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServerConfigCustom'
    put:
      summary: Set instance runtime configuration
      operationId: putCustomConfig
      tags:
        - Config
      security:
        - OAuth2:
          - admin
      responses:
        '200':
          description: successful operation
        '400':
          x-summary: field inconsistencies
          description: >
            Arises when:
              - the emailer is disabled and the instance is open to registrations
              - webtorrent and hls are disabled with transcoding enabled - you need at least one enabled
    delete:
      summary: Delete instance runtime configuration
      operationId: delCustomConfig
      tags:
        - Config
      security:
        - OAuth2:
          - admin
      responses:
        '200':
          description: successful operation

  /custom-pages/homepage/instance:
    get:
      summary: Get instance custom homepage
      tags:
        - Homepage
      responses:
        '404':
          description: No homepage set
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomHomepage'
    put:
      summary: Set instance custom homepage
      tags:
        - Homepage
      security:
        - OAuth2:
          - admin
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
                  description: content of the homepage, that will be injected in the client
      responses:
        '204':
          description: successful operation

  /jobs/pause:
    post:
      summary: Pause job queue
      security:
        - OAuth2:
          - admin
      tags:
        - Job
      responses:
        '204':
          description: successful operation

  /jobs/resume:
    post:
      summary: Resume job queue
      security:
        - OAuth2:
          - admin
      tags:
        - Job
      responses:
        '204':
          description: successful operation

  /jobs/{state}:
    get:
      summary: List instance jobs
      operationId: getJobs
      security:
        - OAuth2:
          - admin
      tags:
        - Job
      parameters:
        - name: state
          in: path
          required: true
          description: The state of the job ('' for for no filter)
          schema:
            type: string
            enum:
              - ''
              - active
              - completed
              - failed
              - waiting
              - delayed
        - $ref: '#/components/parameters/jobType'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    maxItems: 100
                    items:
                      $ref: '#/components/schemas/Job'

  /server/followers:
    get:
      tags:
        - Instance Follows
      summary: List instances following the server
      parameters:
        - $ref: '#/components/parameters/followState'
        - $ref: '#/components/parameters/actorType'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Follow'

  '/server/followers/{nameWithHost}':
    delete:
      summary: Remove or reject a follower to your server
      security:
        - OAuth2:
          - admin
      tags:
        - Instance Follows
      parameters:
        - name: nameWithHost
          in: path
          required: true
          description: The remote actor handle to remove from your followers
          schema:
            type: string
            format: email
      responses:
        '204':
          description: successful operation
        '404':
          description: follower not found

  '/server/followers/{nameWithHost}/reject':
    post:
      summary: Reject a pending follower to your server
      security:
        - OAuth2:
          - admin
      tags:
        - Instance Follows
      parameters:
        - name: nameWithHost
          in: path
          required: true
          description: The remote actor handle to remove from your followers
          schema:
            type: string
            format: email
      responses:
        '204':
          description: successful operation
        '404':
          description: follower not found

  '/server/followers/{nameWithHost}/accept':
    post:
      summary: Accept a pending follower to your server
      security:
        - OAuth2:
          - admin
      tags:
        - Instance Follows
      parameters:
        - name: nameWithHost
          in: path
          required: true
          description: The remote actor handle to remove from your followers
          schema:
            type: string
            format: email
      responses:
        '204':
          description: successful operation
        '404':
          description: follower not found

  /server/following:
    get:
      tags:
        - Instance Follows
      summary: List instances followed by the server
      parameters:
        - $ref: '#/components/parameters/followState'
        - $ref: '#/components/parameters/actorType'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Follow'
    post:
      security:
        - OAuth2:
          - admin
      tags:
        - Instance Follows
      summary: Follow a list of actors (PeerTube instance, channel or account)
      responses:
        '204':
          description: successful operation
        '500':
          description: cannot follow a non-HTTPS server
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                hosts:
                  type: array
                  items:
                    type: string
                    format: hostname
                  uniqueItems: true
                handles:
                  type: array
                  items:
                    type: string
                  uniqueItems: true

  '/server/following/{hostOrHandle}':
    delete:
      summary: Unfollow an actor (PeerTube instance, channel or account)
      security:
        - OAuth2:
          - admin
      tags:
        - Instance Follows
      parameters:
        - name: hostOrHandle
          in: path
          required: true
          description: The hostOrHandle to unfollow
          schema:
            type: string
      responses:
        '204':
          description: successful operation
        '404':
          description: host or handle not found

  /users:
    post:
      summary: Create a user
      operationId: addUser
      security:
        - OAuth2:
          - admin
      tags:
        - Users
      responses:
        '200':
          description: user created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AddUserResponse'
          links:
            # GET /users/{id}
            GetUser:
              operationId: getUser
              parameters:
                id: '$response.body#/user/id'
            # PUT /users/{id}
            PutUser:
              operationId: putUser
              parameters:
                id: '$response.body#/user/id'
            # DELETE /users/{id}
            DelUser:
              operationId: delUser
              parameters:
                id: '$response.body#/user/id'
        '403':
          description: insufficient authority to create an admin or moderator
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddUser'
        description: |
          If the smtp server is configured, you can leave the password empty and an email will be sent
          asking the user to set it first.
        required: true
    get:
      summary: List users
      operationId: getUsers
      security:
        - OAuth2:
          - admin
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/usersSearch'
        - $ref: '#/components/parameters/usersBlocked'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/usersSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'

  '/users/{id}':
    parameters:
      - $ref: '#/components/parameters/id'
    delete:
      summary: Delete a user
      security:
        - OAuth2:
          - admin
      tags:
        - Users
      operationId: delUser
      responses:
        '204':
          description: successful operation
    get:
      summary: Get a user
      security:
        - OAuth2: []
      tags:
        - Users
      operationId: getUser
      parameters:
        - name: withStats
          in: query
          description: include statistics about the user (only available as a moderator/admin)
          schema:
            type: boolean
      responses:
        '200':
          x-summary: successful operation
          description: |
            As an admin/moderator, you can request a response augmented with statistics about the user's
            moderation relations and videos usage, by using the `withStats` parameter.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/User'
                  - $ref: '#/components/schemas/UserWithStats'
    put:
      summary: Update a user
      security:
        - OAuth2: []
      tags:
        - Users
      operationId: putUser
      responses:
        '204':
          description: successful operation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUser'
        required: true

  /oauth-clients/local:
    get:
      summary: Login prerequisite
      description: You need to retrieve a client id and secret before [logging in](#operation/getOAuthToken).
      operationId: getOAuthClient
      tags:
        - Session
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OAuthClient'
          links:
            UseOAuthClientToLogin:
              operationId: getOAuthToken
              parameters:
                client_id: '$response.body#/client_id'
                client_secret: '$response.body#/client_secret'
      x-codeSamples:
        - lang: Shell
          source: |
            API="https://peertube2.cpy.re/api/v1"

            ## AUTH
            curl -s "$API/oauth-clients/local"

  /users/token:
    post:
      summary: Login
      operationId: getOAuthToken
      description: With your [client id and secret](#operation/getOAuthClient), you can retrieve an access and refresh tokens.
      tags:
        - Session
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              oneOf:
                - $ref: '#/components/schemas/OAuthToken-password'
                - $ref: '#/components/schemas/OAuthToken-refresh_token'
              discriminator:
                propertyName: grant_type
                mapping:
                  password: '#/components/schemas/OAuthToken-password'
                  refresh_token: '#/components/schemas/OAuthToken-refresh_token'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  token_type:
                    type: string
                    example: Bearer
                  access_token:
                    type: string
                    example: 90286a0bdf0f7315d9d3fe8dabf9e1d2be9c97d0
                    description: valid for 1 day
                  refresh_token:
                    type: string
                    example: 2e0d675df9fc96d2e4ec8a3ebbbf45eca9137bb7
                    description: valid for 2 weeks
                  expires_in:
                    type: integer
                    minimum: 0
                    example: 14399
                  refresh_token_expires_in:
                    type: integer
                    minimum: 0
                    example: 1209600
        '400':
          x-summary: client or credentials are invalid
          description: |
            Disambiguate via `type`:
            - `invalid_client` for an unmatched `client_id`
            - `invalid_grant` for unmatched credentials
        '401':
          x-summary: token expired
          description: |
            Disambiguate via `type`:
            - default value for a regular authentication failure
            - `invalid_token` for an expired token
      x-codeSamples:
        - lang: Shell
          source: |
            ## DEPENDENCIES: jq
            API="https://peertube2.cpy.re/api/v1"
            USERNAME="<your_username>"
            PASSWORD="<your_password>"

            ## AUTH
            client_id=$(curl -s "$API/oauth-clients/local" | jq -r ".client_id")
            client_secret=$(curl -s "$API/oauth-clients/local" | jq -r ".client_secret")
            curl -s "$API/users/token" \
              --data client_id="$client_id" \
              --data client_secret="$client_secret" \
              --data grant_type=password \
              --data username="$USERNAME" \
              --data password="$PASSWORD" \
              | jq -r ".access_token"

  /users/revoke-token:
    post:
      summary: Logout
      description: Revokes your access token and its associated refresh token, destroying your current session.
      operationId: revokeOAuthToken
      tags:
        - Session
      security:
        - OAuth2: []
      responses:
        '200':
          description: successful operation

  /users/register:
    post:
      summary: Register a user
      operationId: registerUser
      tags:
        - Users
        - Register
      responses:
        '204':
          description: successful operation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterUser'
        required: true

  /users/{id}/verify-email:
    post:
      summary: Verify a user
      operationId: verifyUser
      description: |
        Following a user registration, the new user will receive an email asking to click a link
        containing a secret.
      tags:
        - Users
        - Register
      parameters:
        - $ref: '#/components/parameters/id'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                verificationString:
                  type: string
                  format: url
                isPendingEmail:
                  type: boolean
              required:
                - verificationString
      responses:
        '204':
          description: successful operation
        '403':
          description: invalid verification string
        '404':
          description: user not found

  /users/ask-send-verify-email:
    post:
      summary: Resend user verification link
      operationId: resendEmailToVerifyUser
      tags:
        - Users
        - Register
      responses:
        '204':
          description: successful operation

  /users/me:
    get:
      summary: Get my user information
      operationId: getUserInfo
      security:
        - OAuth2:
          - user
      tags:
        - My User
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
    put:
      summary: Update my user information
      operationId: putUserInfo
      security:
        - OAuth2:
          - user
      tags:
        - My User
      responses:
        '204':
          description: successful operation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateMe'
        required: true

  /users/me/videos/imports:
    get:
      summary: Get video imports of my user
      security:
        - OAuth2:
          - user
      tags:
        - Videos
        - My User
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoImportsList'

  /users/me/video-quota-used:
    get:
      summary: Get my user used quota
      security:
        - OAuth2:
          - user
      tags:
        - My User
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  videoQuotaUsed:
                    type: number
                    description: The user video quota used so far in bytes
                    example: 16810141515
                  videoQuotaUsedDaily:
                    type: number
                    description: The user video quota used today in bytes
                    example: 1681014151

  '/users/me/videos/{videoId}/rating':
    get:
      summary: Get rate of my user for a video
      security:
        - OAuth2: []
      tags:
        - My User
        - Video Rates
      parameters:
        - name: videoId
          in: path
          required: true
          description: The video id
          schema:
            $ref: '#/components/schemas/Video/properties/id'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetMeVideoRating'

  /users/me/videos:
    get:
      summary: Get videos of my user
      security:
        - OAuth2:
          - user
      tags:
        - My User
        - Videos
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoListResponse'

  /users/me/subscriptions:
    get:
      summary: Get my user subscriptions
      security:
        - OAuth2:
          - user
      tags:
        - My Subscriptions
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoChannelList'
    post:
      tags:
        - My Subscriptions
      summary: Add subscription to my user
      security:
        - OAuth2:
          - user
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uri:
                  type: string
                  format: uri
                  description: uri of the video channels to subscribe to
              required:
                - uri
            examples:
              default:
                value:
                  uri: 008a0e54-375d-49d0-8379-143202e24152@video.lqdn.fr
      responses:
        '200':
          description: successful operation

  /users/me/subscriptions/exist:
    get:
      summary: Get if subscriptions exist for my user
      security:
        - OAuth2:
          - user
      tags:
        - My Subscriptions
      parameters:
        - $ref: '#/components/parameters/subscriptionsUris'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object

  /users/me/subscriptions/videos:
    get:
      summary: List videos of subscriptions of my user
      security:
        - OAuth2:
          - user
      tags:
        - My Subscriptions
        - Videos
      parameters:
        - $ref: '#/components/parameters/categoryOneOf'
        - $ref: '#/components/parameters/isLive'
        - $ref: '#/components/parameters/tagsOneOf'
        - $ref: '#/components/parameters/tagsAllOf'
        - $ref: '#/components/parameters/licenceOneOf'
        - $ref: '#/components/parameters/languageOneOf'
        - $ref: '#/components/parameters/nsfw'
        - $ref: '#/components/parameters/isLocal'
        - $ref: '#/components/parameters/include'
        - $ref: '#/components/parameters/privacyOneOf'
        - $ref: '#/components/parameters/hasHLSFiles'
        - $ref: '#/components/parameters/hasWebtorrentFiles'
        - $ref: '#/components/parameters/skipCount'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/videosSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoListResponse'

  '/users/me/subscriptions/{subscriptionHandle}':
    get:
      summary: Get subscription of my user
      security:
        - OAuth2:
          - user
      tags:
        - My Subscriptions
      parameters:
        - $ref: '#/components/parameters/subscriptionHandle'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoChannel'
    delete:
      summary: Delete subscription of my user
      security:
        - OAuth2:
          - user
      tags:
        - My Subscriptions
      parameters:
        - $ref: '#/components/parameters/subscriptionHandle'
      responses:
        '200':
          description: successful operation

  /users/me/notifications:
    get:
      summary: List my notifications
      security:
        - OAuth2: []
      tags:
        - My Notifications
      parameters:
        - name: unread
          in: query
          description: only list unread notifications
          schema:
            type: boolean
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotificationListResponse'

  /users/me/notifications/read:
    post:
      summary: Mark notifications as read by their id
      security:
        - OAuth2: []
      tags:
        - My Notifications
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  description: ids of the notifications to mark as read
                  items:
                    type: integer
              required:
                - ids
      responses:
        '204':
          description: successful operation

  /users/me/notifications/read-all:
    post:
      summary: Mark all my notification as read
      security:
        - OAuth2: []
      tags:
        - My Notifications
      responses:
        '204':
          description: successful operation

  /users/me/notification-settings:
    put:
      summary: Update my notification settings
      security:
        - OAuth2: []
      tags:
        - My Notifications
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                newVideoFromSubscription:
                  $ref: '#/components/schemas/NotificationSettingValue'
                newCommentOnMyVideo:
                  $ref: '#/components/schemas/NotificationSettingValue'
                abuseAsModerator:
                  $ref: '#/components/schemas/NotificationSettingValue'
                videoAutoBlacklistAsModerator:
                  $ref: '#/components/schemas/NotificationSettingValue'
                blacklistOnMyVideo:
                  $ref: '#/components/schemas/NotificationSettingValue'
                myVideoPublished:
                  $ref: '#/components/schemas/NotificationSettingValue'
                myVideoImportFinished:
                  $ref: '#/components/schemas/NotificationSettingValue'
                newFollow:
                  $ref: '#/components/schemas/NotificationSettingValue'
                newUserRegistration:
                  $ref: '#/components/schemas/NotificationSettingValue'
                commentMention:
                  $ref: '#/components/schemas/NotificationSettingValue'
                newInstanceFollower:
                  $ref: '#/components/schemas/NotificationSettingValue'
                autoInstanceFollowing:
                  $ref: '#/components/schemas/NotificationSettingValue'
      responses:
        '204':
          description: successful operation

  /users/me/history/videos:
    get:
      summary: List watched videos history
      security:
        - OAuth2: []
      tags:
        - My History
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/search'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoListResponse'

  /users/me/history/videos/{videoId}:
    delete:
      summary: Delete history element
      security:
        - OAuth2: []
      tags:
        - My History
      parameters:
        - name: videoId
          in: path
          required: true
          schema:
            $ref: '#/components/schemas/Video/properties/id'
      responses:
        '204':
          description: successful operation

  /users/me/history/videos/remove:
    post:
      summary: Clear video history
      security:
        - OAuth2: []
      tags:
        - My History
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                beforeDate:
                  description: history before this date will be deleted
                  type: string
                  format: date-time
      responses:
        '204':
          description: successful operation

  /users/me/avatar/pick:
    post:
      summary: Update my user avatar
      security:
        - OAuth2: []
      tags:
        - My User
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  avatar:
                    $ref: '#/components/schemas/ActorImage'
        '413':
          description: image file too large
          headers:
            X-File-Maximum-Size:
              schema:
                type: string
                format: Nginx size
              description: Maximum file size for the avatar
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                avatarfile:
                  description: The file to upload
                  type: string
                  format: binary
            encoding:
              avatarfile:
                contentType: image/png, image/jpeg

  /users/me/avatar:
    delete:
      summary: Delete my avatar
      security:
        - OAuth2: []
      tags:
        - My User
      responses:
        '204':
          description: successful operation

  /videos/ownership:
    get:
      summary: List video ownership changes
      tags:
        - Video Ownership Change
      security:
        - OAuth2: []
      responses:
        '200':
          description: successful operation

  '/videos/ownership/{id}/accept':
    post:
      summary: Accept ownership change request
      tags:
        - Video Ownership Change
      security:
        - OAuth2: []
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation
        '403':
          description: cannot terminate an ownership change of another user
        '404':
          description: video owneship change not found

  '/videos/ownership/{id}/refuse':
    post:
      summary: Refuse ownership change request
      tags:
        - Video Ownership Change
      security:
        - OAuth2: []
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation
        '403':
          description: cannot terminate an ownership change of another user
        '404':
          description: video owneship change not found

  '/videos/{id}/give-ownership':
    post:
      summary: Request ownership change
      tags:
        - Video Ownership Change
      security:
        - OAuth2: []
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                username:
                  type: string
              required:
                - username
      responses:
        '204':
          description: successful operation
        '400':
          description: changing video ownership to a remote account is not supported yet
        '404':
          description: video not found

  /videos:
    get:
      summary: List videos
      operationId: getVideos
      tags:
        - Video
      parameters:
        - $ref: '#/components/parameters/categoryOneOf'
        - $ref: '#/components/parameters/isLive'
        - $ref: '#/components/parameters/tagsOneOf'
        - $ref: '#/components/parameters/tagsAllOf'
        - $ref: '#/components/parameters/licenceOneOf'
        - $ref: '#/components/parameters/languageOneOf'
        - $ref: '#/components/parameters/nsfw'
        - $ref: '#/components/parameters/isLocal'
        - $ref: '#/components/parameters/include'
        - $ref: '#/components/parameters/privacyOneOf'
        - $ref: '#/components/parameters/hasHLSFiles'
        - $ref: '#/components/parameters/hasWebtorrentFiles'
        - $ref: '#/components/parameters/skipCount'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/videosSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoListResponse'

  /videos/categories:
    get:
      summary: List available video categories
      operationId: getCategories
      tags:
        - Video
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/api/v1/videos/categories

  /videos/licences:
    get:
      summary: List available video licences
      operationId: getLicences
      tags:
        - Video
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/api/v1/videos/licences

  /videos/languages:
    get:
      summary: List available video languages
      operationId: getLanguages
      tags:
        - Video
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/api/v1/videos/languages

  /videos/privacies:
    get:
      summary: List available video privacy policies
      operationId: getPrivacyPolicies
      tags:
        - Video
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/api/v1/videos/privacies

  '/videos/{id}':
    put:
      summary: Update a video
      operationId: putVideo
      security:
        - OAuth2: []
      tags:
        - Video
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                thumbnailfile:
                  description: Video thumbnail file
                  type: string
                  format: binary
                previewfile:
                  description: Video preview file
                  type: string
                  format: binary
                category:
                  $ref: '#/components/schemas/VideoCategorySet'
                licence:
                  $ref: '#/components/schemas/VideoLicenceSet'
                language:
                  $ref: '#/components/schemas/VideoLanguageSet'
                privacy:
                  $ref: '#/components/schemas/VideoPrivacySet'
                description:
                  description: Video description
                  type: string
                waitTranscoding:
                  description: Whether or not we wait transcoding before publish the video
                  type: string
                support:
                  description: A text tell the audience how to support the video creator
                  example: Please support our work on https://soutenir.framasoft.org/en/ <3
                  type: string
                nsfw:
                  description: Whether or not this video contains sensitive content
                  type: boolean
                name:
                  description: Video name
                  type: string
                  minLength: 3
                  maxLength: 120
                tags:
                  description: Video tags (maximum 5 tags each between 2 and 30 characters)
                  type: array
                  minItems: 1
                  maxItems: 5
                  items:
                    type: string
                    minLength: 2
                    maxLength: 30
                commentsEnabled:
                  description: Enable or disable comments for this video
                  type: boolean
                downloadEnabled:
                  description: Enable or disable downloading for this video
                  type: boolean
                originallyPublishedAt:
                  description: Date when the content was originally published
                  type: string
                  format: date-time
                scheduleUpdate:
                  $ref: '#/components/schemas/VideoScheduledUpdate'
            encoding:
              thumbnailfile:
                contentType: image/jpeg
              previewfile:
                contentType: image/jpeg
    get:
      summary: Get a video
      operationId: getVideo
      tags:
        - Video
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoDetails'
    delete:
      summary: Delete a video
      operationId: delVideo
      security:
        - OAuth2: []
      tags:
        - Video
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation

  '/videos/{id}/description':
    get:
      summary: Get complete video description
      operationId: getVideoDesc
      tags:
        - Video
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                nullable: true
                type: string
                minLength: 3
                maxLength: 10000
                example: |
                  **[Want to help to translate this video?](https://weblate.framasoft.org/projects/what-is-peertube-video/)**\r\n\r\n**Take back the control of your videos! [#JoinPeertube](https://joinpeertube.org)**

  '/videos/{id}/views':
    post:
      summary: Add a view to a video
      operationId: addView
      tags:
        - Video
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation

  '/videos/{id}/watching':
    put:
      summary: Set watching progress of a video
      operationId: setProgress
      tags:
        - Video
      security:
        - OAuth2: []
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserWatchingVideo'
        required: true
      responses:
        '204':
          description: successful operation

  /videos/upload:
    post:
      summary: Upload a video
      description: Uses a single request to upload a video.
      operationId: uploadLegacy
      security:
        - OAuth2: []
      tags:
        - Video
        - Video Upload
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoUploadResponse'
        '403':
          description: video didn't pass upload filter
        '408':
          description: upload has timed out
        '413':
          x-summary: video file too large, due to quota or max body size limit set by the reverse-proxy
          description: |
            If the response has no body, it means the reverse-proxy didn't let it through. Otherwise disambiguate via `type`:
            - `quota_reached` for quota limits wether daily or global
          headers:
            X-File-Maximum-Size:
              schema:
                type: string
                format: Nginx size
              description: Maximum file size for the video
        '415':
          description: video type unsupported
        '422':
          description: video unreadable
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/VideoUploadRequestLegacy'
            encoding:
              videofile:
                contentType: video/mp4, video/webm, video/ogg, video/avi, video/quicktime, video/x-msvideo, video/x-flv, video/x-matroska, application/octet-stream
              thumbnailfile:
                contentType: image/jpeg
              previewfile:
                contentType: image/jpeg
      x-codeSamples:
        - lang: Shell
          source: |
            ## DEPENDENCIES: jq
            USERNAME="<your_username>"
            PASSWORD="<your_password>"
            FILE_PATH="<your_file_path>"
            CHANNEL_ID="<your_channel_id>"
            NAME="<video_name>"
            API="https://peertube2.cpy.re/api/v1"

            ## AUTH
            client_id=$(curl -s "$API/oauth-clients/local" | jq -r ".client_id")
            client_secret=$(curl -s "$API/oauth-clients/local" | jq -r ".client_secret")
            token=$(curl -s "$API/users/token" \
              --data client_id="$client_id" \
              --data client_secret="$client_secret" \
              --data grant_type=password \
              --data username="$USERNAME" \
              --data password="$PASSWORD" \
              | jq -r ".access_token")

            ## VIDEO UPLOAD
            curl -s "$API/videos/upload" \
              -H "Authorization: Bearer $token" \
              --max-time 600 \
              --form videofile=@"$FILE_PATH" \
              --form channelId=$CHANNEL_ID \
              --form name="$NAME"

  /videos/upload-resumable:
    post:
      summary: Initialize the resumable upload of a video
      description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to initialize the upload of a video
      operationId: uploadResumableInit
      security:
        - OAuth2: []
      tags:
        - Video
        - Video Upload
      parameters:
        - name: X-Upload-Content-Length
          in: header
          schema:
            type: number
            example: 2469036
          required: true
          description: Number of bytes that will be uploaded in subsequent requests. Set this value to the size of the file you are uploading.
        - name: X-Upload-Content-Type
          in: header
          schema:
            type: string
            format: mimetype
            example: video/mp4
          required: true
          description: MIME type of the file that you are uploading. Depending on your instance settings, acceptable values might vary.
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VideoUploadRequestResumable'
      responses:
        '200':
          description: file already exists, send a [`resume`](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) request instead
        '201':
          description: created
          headers:
            Location:
              schema:
                type: string
                format: url
                example: /api/v1/videos/upload-resumable?upload_id=471e97554f21dec3b8bb5d4602939c51
            Content-Length:
              schema:
                type: number
                example: 0
        '413':
          x-summary: video file too large, due to quota, absolute max file size or concurrent partial upload limit
          description: |
            Disambiguate via `type`:
            - `max_file_size_reached` for the absolute file size limit
            - `quota_reached` for quota limits whether daily or global
        '415':
          description: video type unsupported
    put:
      summary: Send chunk for the resumable upload of a video
      description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to continue, pause or resume the upload of a video
      operationId: uploadResumable
      security:
        - OAuth2: []
      tags:
        - Video
        - Video Upload
      parameters:
        - name: upload_id
          in: query
          required: true
          description: |
            Created session id to proceed with. If you didn't send chunks in the last 12 hours, it is
            not valid anymore and you need to initialize a new upload.
          schema:
            type: string
        - name: Content-Range
          in: header
          schema:
            type: string
            example: bytes 0-262143/2469036
          required: true
          description: |
            Specifies the bytes in the file that the request is uploading.

            For example, a value of `bytes 0-262143/1000000` shows that the request is sending the first
            262144 bytes (256 x 1024) in a 2,469,036 byte file.
        - name: Content-Length
          in: header
          schema:
            type: number
            example: 262144
          required: true
          description: |
            Size of the chunk that the request is sending.

            The chunk size __must be a multiple of 256 KB__, and unlike [Google Resumable](https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol)
            doesn't mandate for chunks to have the same size throughout the upload sequence.

            Remember that larger chunks are more efficient. PeerTube's web client uses chunks varying from
            1048576 bytes (~1MB) and increases or reduces size depending on connection health.
      requestBody:
        content:
          application/octet-stream:
            schema:
              type: string
              format: binary
      responses:
        '200':
          description: last chunk received
          headers:
            Content-Length:
              schema:
                type: number
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoUploadResponse'
        '308':
          description: resume incomplete
          headers:
            Range:
              schema:
                type: string
                example: bytes=0-262143
            Content-Length:
              schema:
                type: number
                example: 0
        '403':
          description: video didn't pass upload filter
        '404':
          description: upload not found
        '409':
          description: chunk doesn't match range
        '422':
          description: video unreadable
        '429':
          description: too many concurrent requests
        '503':
          description: upload is already being processed
          headers:
            'Retry-After':
              schema:
                type: number
                example: 300
    delete:
      summary: Cancel the resumable upload of a video, deleting any data uploaded so far
      description: Uses [a resumable protocol](https://github.com/kukhariev/node-uploadx/blob/master/proto.md) to cancel the upload of a video
      operationId: uploadResumableCancel
      security:
        - OAuth2: []
      tags:
        - Video
        - Video Upload
      parameters:
        - name: upload_id
          in: query
          required: true
          description: |
            Created session id to proceed with. If you didn't send chunks in the last 12 hours, it is
            not valid anymore and the upload session has already been deleted with its data ;-)
          schema:
            type: string
        - name: Content-Length
          in: header
          required: true
          schema:
            type: number
            example: 0
      responses:
        '204':
          description: upload cancelled
          headers:
            Content-Length:
              schema:
                type: number
                example: 0
        '404':
          description: upload not found

  /videos/imports:
    post:
      summary: Import a video
      description: Import a torrent or magnetURI or HTTP resource (if enabled by the instance administrator)
      operationId: importVideo
      security:
        - OAuth2: []
      tags:
        - Video Imports
        - Video Upload
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/VideoCreateImport'
            encoding:
              torrentfile:
                contentType: application/x-bittorrent
              thumbnailfile:
                contentType: image/jpeg
              previewfile:
                contentType: image/jpeg
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoUploadResponse'
        '400':
          description: '`magnetUri` or `targetUrl` or a torrent file missing'
        '403':
          description: video didn't pass pre-import filter
        '409':
          description: HTTP or Torrent/magnetURI import not enabled

  /videos/imports/{id}/cancel:
    post:
      summary: Cancel video import
      description: Cancel a pending video import
      security:
        - OAuth2: []
      tags:
        - Video Imports
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '204':
          description: successful operation

  /videos/imports/{id}:
    delete:
      summary: Delete video import
      description: Delete ended video import
      security:
        - OAuth2: []
      tags:
        - Video Imports
      parameters:
        - $ref: '#/components/parameters/id'
      responses:
        '204':
          description: successful operation

  /videos/live:
    post:
      summary: Create a live
      operationId: addLive
      security:
        - OAuth2: []
      tags:
        - Live Videos
        - Video
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoUploadResponse'
        '400':
          x-summary: validation error, or conflicting `saveReplay` and `permanentLive` parameter set
          description: |
            Disambiguate via `type`:
            - default type for a validation error
            - `live_conflicting_permanent_and_save_replay` for conflicting parameters set
        '403':
          x-summary: live is not enabled, allow replay is not enabled, or max instance/user live videos limit is exceeded
          description: |
            Disambiguate via `type`:
            - `live_not_enabled` for a disabled live feature
            - `live_not_allowing_replay` for a disabled replay feature
            - `max_instance_lives_limit_reached` for the absolute concurrent live limit
            - `max_user_lives_limit_reached` for the user concurrent live limit
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                channelId:
                  description: Channel id that will contain this live video
                  type: integer
                saveReplay:
                  type: boolean
                permanentLive:
                  description: User can stream multiple times in a permanent live
                  type: boolean
                thumbnailfile:
                  description: Live video/replay thumbnail file
                  type: string
                  format: binary
                previewfile:
                  description: Live video/replay preview file
                  type: string
                  format: binary
                privacy:
                  $ref: '#/components/schemas/VideoPrivacySet'
                category:
                  $ref: '#/components/schemas/VideoCategorySet'
                licence:
                  $ref: '#/components/schemas/VideoLicenceSet'
                language:
                  $ref: '#/components/schemas/VideoLanguageSet'
                description:
                  description: Live video/replay description
                  type: string
                support:
                  description: A text tell the audience how to support the creator
                  example: Please support our work on https://soutenir.framasoft.org/en/ <3
                  type: string
                nsfw:
                  description: Whether or not this live video/replay contains sensitive content
                  type: boolean
                name:
                  description: Live video/replay name
                  type: string
                  minLength: 3
                  maxLength: 120
                tags:
                  description: Live video/replay tags (maximum 5 tags each between 2 and 30 characters)
                  type: array
                  minItems: 1
                  maxItems: 5
                  items:
                    type: string
                    minLength: 2
                    maxLength: 30
                commentsEnabled:
                  description: Enable or disable comments for this live video/replay
                  type: boolean
                downloadEnabled:
                  description: Enable or disable downloading for the replay of this live video
                  type: boolean
              required:
                - channelId
                - name
            encoding:
              thumbnailfile:
                contentType: image/jpeg
              previewfile:
                contentType: image/jpeg

  /videos/live/{id}:
    get:
      summary: Get information about a live
      operationId: getLiveId
      security:
        - OAuth2: []
      tags:
        - Live Videos
        - Video
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LiveVideoResponse'
    put:
      summary: Update information about a live
      operationId: updateLiveId
      security:
        - OAuth2: []
      tags:
        - Live Videos
        - Video
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LiveVideoUpdate'
      responses:
        '204':
          description: successful operation
        '400':
          description: bad parameters or trying to update a live that has already started
        '403':
          description: trying to save replay of the live but saving replay is not enabled on the instance

  /users/me/abuses:
    get:
      summary: List my abuses
      operationId: getMyAbuses
      security:
        - OAuth2: []
      tags:
        - Abuses
        - My User
      parameters:
        - name: id
          in: query
          description: only list the report with this id
          schema:
            type: integer
        - name: state
          in: query
          schema:
            $ref: '#/components/schemas/AbuseStateSet'
        - $ref: '#/components/parameters/abusesSort'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Abuse'

  /abuses:
    get:
      summary: List abuses
      operationId: getAbuses
      security:
        - OAuth2:
          - admin
          - moderator
      tags:
        - Abuses
      parameters:
        - name: id
          in: query
          description: only list the report with this id
          schema:
            type: integer
        - name: predefinedReason
          in: query
          description: predefined reason the listed reports should contain
          schema:
            $ref: '#/components/schemas/PredefinedAbuseReasons'
        - name: search
          in: query
          description: plain search that will match with video titles, reporter names and more
          schema:
            type: string
        - name: state
          in: query
          schema:
            $ref: '#/components/schemas/AbuseStateSet'
        - name: searchReporter
          in: query
          description: only list reports of a specific reporter
          schema:
            type: string
        - name: searchReportee
          description: only list reports of a specific reportee
          in: query
          schema:
            type: string
        - name: searchVideo
          in: query
          description: only list reports of a specific video
          schema:
            type: string
        - name: searchVideoChannel
          in: query
          description: only list reports of a specific video channel
          schema:
            type: string
        - name: videoIs
          in: query
          description: only list deleted or blocklisted videos
          schema:
            type: string
            enum:
            - 'deleted'
            - 'blacklisted'
        - name: filter
          in: query
          description: only list account, comment or video reports
          schema:
            type: string
            enum:
            - 'video'
            - 'comment'
            - 'account'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/abusesSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Abuse'
    post:
      summary: Report an abuse
      security:
        - OAuth2: []
      tags:
        - Abuses
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  description: Reason why the user reports this video
                  type: string
                  minLength: 2
                  maxLength: 3000
                predefinedReasons:
                  $ref: '#/components/schemas/PredefinedAbuseReasons'
                video:
                  type: object
                  properties:
                    id:
                      description: Video id to report
                      allOf:
                        - $ref: '#/components/schemas/Video/properties/id'
                    startAt:
                      type: integer
                      format: seconds
                      description: Timestamp in the video that marks the beginning of the report
                      minimum: 0
                    endAt:
                      type: integer
                      format: seconds
                      description: Timestamp in the video that marks the ending of the report
                      minimum: 0
                comment:
                  type: object
                  properties:
                    id:
                      description: Comment id to report
                      allOf:
                        - $ref: '#/components/schemas/VideoComment/properties/id'
                account:
                  type: object
                  properties:
                    id:
                      description: Account id to report
                      type: integer
              required:
                - reason
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  abuse:
                    type: object
                    properties:
                      id:
                        $ref: '#/components/schemas/id'
        '400':
          description: incorrect request parameters

  '/abuses/{abuseId}':
    put:
      summary: Update an abuse
      security:
        - OAuth2:
          - admin
          - moderator
      tags:
        - Abuses
      parameters:
        - $ref: '#/components/parameters/abuseId'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                state:
                  $ref: '#/components/schemas/AbuseStateSet'
                moderationComment:
                  type: string
                  description: Update the report comment visible only to the moderation team
                  minLength: 2
                  maxLength: 3000
      responses:
        '204':
          description: successful operation
        '404':
          description: abuse not found
    delete:
      tags:
        - Abuses
      summary: Delete an abuse
      security:
        - OAuth2:
          - admin
          - moderator
      parameters:
        - $ref: '#/components/parameters/abuseId'
      responses:
        '204':
          description: successful operation
        '404':
          description: block not found

  '/abuses/{abuseId}/messages':
    get:
      summary: List messages of an abuse
      security:
        - OAuth2: []
      tags:
        - Abuses
      parameters:
        - $ref: '#/components/parameters/abuseId'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/AbuseMessage'
    post:
      summary: Add message to an abuse
      security:
        - OAuth2: []
      tags:
        - Abuses
      parameters:
        - $ref: '#/components/parameters/abuseId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                message:
                  description: Message to send
                  type: string
                  minLength: 2
                  maxLength: 3000
              required:
                - message
      responses:
        '200':
          description: successful operation
        '400':
          description: incorrect request parameters

  '/abuses/{abuseId}/messages/{abuseMessageId}':
    delete:
      summary: Delete an abuse message
      security:
        - OAuth2: []
      tags:
        - Abuses
      parameters:
        - $ref: '#/components/parameters/abuseId'
        - $ref: '#/components/parameters/abuseMessageId'
      responses:
        '204':
          description: successful operation

  '/videos/{id}/blacklist':
    post:
      summary: Block a video
      operationId: addVideoBlock
      security:
        - OAuth2:
          - admin
          - moderator
      tags:
        - Video Blocks
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation
    delete:
      summary: Unblock a video by its id
      operationId: delVideoBlock
      security:
        - OAuth2:
          - admin
          - moderator
      tags:
        - Video Blocks
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation
        '404':
          description: block not found

  /videos/blacklist:
    get:
      tags:
        - Video Blocks
      summary: List video blocks
      operationId: getVideoBlocks
      security:
        - OAuth2:
          - admin
          - moderator
      parameters:
        - name: type
          in: query
          description: >
            list only blocks that match this type:

            - `1`: manual block

            - `2`: automatic block that needs review
          schema:
            type: integer
            enum:
              - 1
              - 2
        - name: search
          in: query
          description: plain search that will match with video titles, and more
          schema:
            type: string
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/blacklistsSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/VideoBlacklist'

  /videos/{id}/captions:
    get:
      summary: List captions of a video
      operationId: getVideoCaptions
      tags:
        - Video Captions
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/VideoCaption'

  /videos/{id}/captions/{captionLanguage}:
    put:
      summary: Add or replace a video caption
      operationId: addVideoCaption
      security:
        - OAuth2:
          - user
      tags:
        - Video Captions
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
        - $ref: '#/components/parameters/captionLanguage'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                captionfile:
                  description: The file to upload.
                  type: string
                  format: binary
            encoding:
              captionfile:
                contentType: text/vtt, application/x-subrip, text/plain
      responses:
        '204':
          description: successful operation
        '404':
          description: video or language not found
    delete:
      summary: Delete a video caption
      operationId: delVideoCaption
      security:
        - OAuth2:
          - user
      tags:
        - Video Captions
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
        - $ref: '#/components/parameters/captionLanguage'
      responses:
        '204':
          description: successful operation
        '404':
          description: video or language or caption for that language not found

  /video-channels:
    get:
      summary: List video channels
      operationId: getVideoChannels
      tags:
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoChannelList'
    post:
      summary: Create a video channel
      operationId: addVideoChannel
      security:
        - OAuth2: []
      tags:
        - Video Channels
      responses:
        '204':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  videoChannel:
                    type: object
                    properties:
                      id:
                        $ref: '#/components/schemas/VideoChannel/properties/id'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VideoChannelCreate'

  '/video-channels/{channelHandle}':
    get:
      summary: Get a video channel
      operationId: getVideoChannel
      tags:
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/channelHandle'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoChannel'
    put:
      summary: Update a video channel
      operationId: putVideoChannel
      security:
        - OAuth2: []
      tags:
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/channelHandle'
      responses:
        '204':
          description: successful operation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VideoChannelUpdate'
    delete:
      summary: Delete a video channel
      operationId: delVideoChannel
      security:
        - OAuth2: []
      tags:
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/channelHandle'
      responses:
        '204':
          description: successful operation

  '/video-channels/{channelHandle}/videos':
    get:
      summary: List videos of a video channel
      operationId: getVideoChannelVideos
      tags:
        - Video
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/channelHandle'
        - $ref: '#/components/parameters/categoryOneOf'
        - $ref: '#/components/parameters/isLive'
        - $ref: '#/components/parameters/tagsOneOf'
        - $ref: '#/components/parameters/tagsAllOf'
        - $ref: '#/components/parameters/licenceOneOf'
        - $ref: '#/components/parameters/languageOneOf'
        - $ref: '#/components/parameters/nsfw'
        - $ref: '#/components/parameters/isLocal'
        - $ref: '#/components/parameters/include'
        - $ref: '#/components/parameters/privacyOneOf'
        - $ref: '#/components/parameters/hasHLSFiles'
        - $ref: '#/components/parameters/hasWebtorrentFiles'
        - $ref: '#/components/parameters/skipCount'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/videosSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoListResponse'

  '/video-channels/{channelHandle}/followers':
    get:
      tags:
        - Video Channels
      summary: 'List followers of a video channel'
      security:
        - OAuth2: []
      operationId: getVideoChannelFollowers
      parameters:
        - $ref: '#/components/parameters/channelHandle'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/followersSort'
        - $ref: '#/components/parameters/search'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Follow'

  '/video-channels/{channelHandle}/avatar/pick':
    post:
      summary: Update channel avatar
      security:
        - OAuth2: []
      tags:
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/channelHandle'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  avatar:
                    $ref: '#/components/schemas/ActorImage'
        '413':
          description: image file too large
          headers:
            X-File-Maximum-Size:
              schema:
                type: string
                format: Nginx size
              description: Maximum file size for the avatar
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                avatarfile:
                  description: The file to upload.
                  type: string
                  format: binary
            encoding:
              avatarfile:
                contentType: image/png, image/jpeg

  '/video-channels/{channelHandle}/avatar':
    delete:
      summary: Delete channel avatar
      security:
        - OAuth2: []
      tags:
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/channelHandle'
      responses:
        '204':
          description: successful operation

  '/video-channels/{channelHandle}/banner/pick':
    post:
      summary: Update channel banner
      security:
        - OAuth2: []
      tags:
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/channelHandle'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  banner:
                    $ref: '#/components/schemas/ActorImage'
        '413':
          description: image file too large
          headers:
            X-File-Maximum-Size:
              schema:
                type: string
                format: Nginx size
              description: Maximum file size for the banner
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                bannerfile:
                  description: The file to upload.
                  type: string
                  format: binary
            encoding:
              bannerfile:
                contentType: image/png, image/jpeg

  '/video-channels/{channelHandle}/banner':
    delete:
      summary: Delete channel banner
      security:
        - OAuth2: []
      tags:
        - Video Channels
      parameters:
        - $ref: '#/components/parameters/channelHandle'
      responses:
        '204':
          description: successful operation

  /video-playlists/privacies:
    get:
      summary: List available playlist privacy policies
      operationId: getPlaylistPrivacyPolicies
      tags:
        - Video Playlists
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/api/v1/video-playlists/privacies

  /video-playlists:
    get:
      summary: List video playlists
      operationId: getPlaylists
      tags:
        - Video Playlists
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/VideoPlaylist'
    post:
      summary: Create a video playlist
      description: If the video playlist is set as public, `videoChannelId` is mandatory.
      operationId: addPlaylist
      security:
        - OAuth2: []
      tags:
        - Video Playlists
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  videoPlaylist:
                    type: object
                    properties:
                      id:
                        $ref: '#/components/schemas/VideoPlaylist/properties/id'
                      uuid:
                        $ref: '#/components/schemas/VideoPlaylist/properties/uuid'
                      shortUUID:
                        $ref: '#/components/schemas/VideoPlaylist/properties/shortUUID'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                displayName:
                  description: Video playlist display name
                  type: string
                  minLength: 1
                  maxLength: 120
                thumbnailfile:
                  description: Video playlist thumbnail file
                  type: string
                  format: binary
                privacy:
                  $ref: '#/components/schemas/VideoPlaylistPrivacySet'
                description:
                  description: Video playlist description
                  type: string
                  minLength: 3
                  maxLength: 1000
                videoChannelId:
                  allOf:
                    - $ref: '#/components/schemas/id'
                  description: Video channel in which the playlist will be published
              required:
                - displayName
            encoding:
              thumbnailfile:
                contentType: image/jpeg

  /video-playlists/{playlistId}:
    get:
      summary: Get a video playlist
      tags:
        - Video Playlists
      parameters:
        - $ref: '#/components/parameters/playlistId'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoPlaylist'
    put:
      summary: Update a video playlist
      description: 'If the video playlist is set as public, the playlist must have a assigned channel.'
      security:
        - OAuth2: []
      tags:
        - Video Playlists
      responses:
        '204':
          description: successful operation
      parameters:
        - $ref: '#/components/parameters/playlistId'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                displayName:
                  description: Video playlist display name
                  type: string
                  minLength: 1
                  maxLength: 120
                thumbnailfile:
                  description: Video playlist thumbnail file
                  type: string
                  format: binary
                privacy:
                  $ref: '#/components/schemas/VideoPlaylistPrivacySet'
                description:
                  description: Video playlist description
                  type: string
                videoChannelId:
                  allOf:
                    - $ref: '#/components/schemas/id'
                  description: Video channel in which the playlist will be published
            encoding:
              thumbnailfile:
                contentType: image/jpeg
    delete:
      summary: Delete a video playlist
      security:
        - OAuth2: []
      tags:
        - Video Playlists
      parameters:
        - $ref: '#/components/parameters/playlistId'
      responses:
        '204':
          description: successful operation

  /video-playlists/{playlistId}/videos:
    get:
      summary: 'List videos of a playlist'
      operationId: getVideoPlaylistVideos
      tags:
        - Videos
        - Video Playlists
      parameters:
        - $ref: '#/components/parameters/playlistId'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoListResponse'
    post:
      summary: Add a video in a playlist
      operationId: addVideoPlaylistVideo
      security:
        - OAuth2: []
      tags:
        - Videos
        - Video Playlists
      parameters:
        - $ref: '#/components/parameters/playlistId'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  videoPlaylistElement:
                    type: object
                    properties:
                      id:
                        type: integer
                        example: 2
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                videoId:
                  oneOf:
                    - $ref: '#/components/schemas/Video/properties/uuid'
                    - $ref: '#/components/schemas/Video/properties/id'
                  description: Video to add in the playlist
                startTimestamp:
                  type: integer
                  format: seconds
                  description: Start the video at this specific timestamp
                stopTimestamp:
                  type: integer
                  format: seconds
                  description: Stop the video at this specific timestamp
              required:
                - videoId

  /video-playlists/{playlistId}/videos/reorder:
    post:
      summary: 'Reorder a playlist'
      operationId: reorderVideoPlaylist
      security:
        - OAuth2: []
      tags:
        - Video Playlists
      parameters:
        - $ref: '#/components/parameters/playlistId'
      responses:
        '204':
          description: successful operation
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                startPosition:
                  type: integer
                  description: 'Start position of the element to reorder'
                  minimum: 1
                insertAfterPosition:
                  type: integer
                  description: 'New position for the block to reorder, to add the block before the first element'
                  minimum: 0
                reorderLength:
                  type: integer
                  description: 'How many element from `startPosition` to reorder'
                  minimum: 1
              required:
                - startPosition
                - insertAfterPosition

  /video-playlists/{playlistId}/videos/{playlistElementId}:
    put:
      summary: Update a playlist element
      operationId: putVideoPlaylistVideo
      security:
        - OAuth2: []
      tags:
        - Video Playlists
      parameters:
        - $ref: '#/components/parameters/playlistId'
        - $ref: '#/components/parameters/playlistElementId'
      responses:
        '204':
          description: successful operation
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                startTimestamp:
                  type: integer
                  format: seconds
                  description: Start the video at this specific timestamp
                stopTimestamp:
                  type: integer
                  format: seconds
                  description: Stop the video at this specific timestamp
    delete:
      summary: Delete an element from a playlist
      operationId: delVideoPlaylistVideo
      security:
        - OAuth2: []
      tags:
        - Video Playlists
      parameters:
        - $ref: '#/components/parameters/playlistId'
        - $ref: '#/components/parameters/playlistElementId'
      responses:
        '204':
          description: successful operation

  '/users/me/video-playlists/videos-exist':
    get:
      summary: Check video exists in my playlists
      security:
        - OAuth2: []
      tags:
        - Video Playlists
      parameters:
        - name: videoIds
          in: query
          required: true
          description: The video ids to check
          schema:
            type: array
            items:
              $ref: '#/components/schemas/Video/properties/id'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  videoId:
                    type: array
                    items:
                      type: object
                      properties:
                        playlistElementId:
                          type: integer
                        playlistId:
                          type: integer
                        startTimestamp:
                          type: integer
                          format: seconds
                        stopTimestamp:
                          type: integer
                          format: seconds

  '/accounts/{name}/video-channels':
    get:
      summary: List video channels of an account
      tags:
        - Video Channels
        - Accounts
      parameters:
        - $ref: '#/components/parameters/name'
        - name: withStats
          in: query
          description: include view statistics for the last 30 days (only if authentified as the account user)
          schema:
            type: boolean
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoChannelList'

  '/accounts/{name}/ratings':
    get:
      summary: List ratings of an account
      security:
        - OAuth2: []
      tags:
        - Accounts
      parameters:
        - $ref: '#/components/parameters/name'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
        - name: rating
          in: query
          required: false
          description: Optionally filter which ratings to retrieve
          schema:
            type: string
            enum:
              - like
              - dislike
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/VideoRating'

  '/videos/{id}/comment-threads':
    get:
      summary: List threads of a video
      tags:
        - Video Comments
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/commentsSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommentThreadResponse'
    post:
      summary: Create a thread
      security:
        - OAuth2: []
      tags:
        - Video Comments
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommentThreadPostResponse'
        '404':
          description: video does not exist
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                text:
                  allOf:
                    - $ref: '#/components/schemas/VideoComment/properties/text'
                  format: markdown
                  maxLength: 10000
              required:
                - text

  '/videos/{id}/comment-threads/{threadId}':
    get:
      summary: Get a thread
      tags:
        - Video Comments
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
        - $ref: '#/components/parameters/threadId'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoCommentThreadTree'

  '/videos/{id}/comments/{commentId}':
    post:
      summary: Reply to a thread of a video
      security:
        - OAuth2: []
      tags:
        - Video Comments
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
        - $ref: '#/components/parameters/commentId'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommentThreadPostResponse'
        '404':
          description: thread or video does not exist
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                text:
                  allOf:
                    - $ref: '#/components/schemas/VideoComment/properties/text'
                  format: markdown
                  maxLength: 10000
              required:
                - text
    delete:
      summary: Delete a comment or a reply
      security:
        - OAuth2: []
      tags:
        - Video Comments
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
        - $ref: '#/components/parameters/commentId'
      responses:
        '204':
          description: successful operation
        '403':
          description: cannot remove comment of another user
        '404':
          description: comment or video does not exist
        '409':
          description: comment is already deleted

  '/videos/{id}/rate':
    put:
      summary: Like/dislike a video
      security:
        - OAuth2: []
      tags:
        - Video Rates
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rating:
                  type: string
                  enum:
                    - like
                    - dislike
              required:
                - rating
      responses:
        '204':
          description: successful operation
        '404':
          description: video does not exist

  '/videos/{id}/hls':
    delete:
      summary: Delete video HLS files
      security:
        - OAuth2:
          - admin
      tags:
        - Video Files
      operationId: delVideoHLS
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation
        '404':
          description: video does not exist
  '/videos/{id}/webtorrent':
    delete:
      summary: Delete video WebTorrent files
      security:
        - OAuth2:
          - admin
      tags:
        - Video Files
      operationId: delVideoWebTorrent
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      responses:
        '204':
          description: successful operation
        '404':
          description: video does not exist

  '/videos/{id}/transcoding':
    post:
      summary: Create a transcoding job
      security:
        - OAuth2:
          - admin
      tags:
        - Video Transcoding
      operationId: createVideoTranscoding
      parameters:
        - $ref: '#/components/parameters/idOrUUID'
      requestBody:
          content:
            application/json:
              schema:
                type: object
                properties:
                  transcodingType:
                    type: string
                    enum:
                      - hls
                      - webtorrent
                required:
                  - transcodingType
      responses:
        '204':
          description: successful operation
        '404':
          description: video does not exist

  /search/videos:
    get:
      tags:
        - Search
      summary: Search videos
      operationId: searchVideos
      parameters:
        - name: search
          in: query
          required: true
          allowEmptyValue: false
          description: >
            String to search. If the user can make a remote URI search, and the string is an URI then the
            PeerTube instance will fetch the remote object and add it to its database. Then,
            you can use the REST API to fetch the complete video information and interact with it.
          schema:
            type: string
        - $ref: '#/components/parameters/categoryOneOf'
        - $ref: '#/components/parameters/isLive'
        - $ref: '#/components/parameters/tagsOneOf'
        - $ref: '#/components/parameters/tagsAllOf'
        - $ref: '#/components/parameters/licenceOneOf'
        - $ref: '#/components/parameters/languageOneOf'
        - $ref: '#/components/parameters/nsfw'
        - $ref: '#/components/parameters/isLocal'
        - $ref: '#/components/parameters/include'
        - $ref: '#/components/parameters/privacyOneOf'
        - $ref: '#/components/parameters/hasHLSFiles'
        - $ref: '#/components/parameters/hasWebtorrentFiles'
        - $ref: '#/components/parameters/skipCount'
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/searchTarget'
        - $ref: '#/components/parameters/videosSearchSort'
        - name: startDate
          in: query
          description: Get videos that are published after this date
          schema:
            type: string
            format: date-time
        - name: endDate
          in: query
          description: Get videos that are published before this date
          schema:
            type: string
            format: date-time
        - name: originallyPublishedStartDate
          in: query
          description: Get videos that are originally published after this date
          schema:
            type: string
            format: date-time
        - name: originallyPublishedEndDate
          in: query
          description: Get videos that are originally published before this date
          schema:
            type: string
            format: date-time
        - name: durationMin
          in: query
          description: Get videos that have this minimum duration
          schema:
            type: integer
        - name: durationMax
          in: query
          description: Get videos that have this maximum duration
          schema:
            type: integer
      callbacks:
        'searchTarget === search-index':
          $ref: '#/components/callbacks/searchIndex'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoListResponse'
        '500':
          description: search index unavailable

  /search/video-channels:
    get:
      tags:
        - Search
      summary: Search channels
      operationId: searchChannels
      parameters:
        - name: search
          in: query
          required: true
          description: >
            String to search. If the user can make a remote URI search, and the string is an URI then the
            PeerTube instance will fetch the remote object and add it to its database. Then,
            you can use the REST API to fetch the complete channel information and interact with it.
          schema:
            type: string
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/searchTarget'
        - $ref: '#/components/parameters/sort'
      callbacks:
        'searchTarget === search-index':
          $ref: '#/components/callbacks/searchIndex'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VideoChannelList'
        '500':
          description: search index unavailable

  /search/video-playlists:
    get:
      tags:
        - Search
      summary: Search playlists
      operationId: searchPlaylists
      parameters:
        - name: search
          in: query
          required: true
          description: >
            String to search. If the user can make a remote URI search, and the string is an URI then the
            PeerTube instance will fetch the remote object and add it to its database. Then,
            you can use the REST API to fetch the complete playlist information and interact with it.
          schema:
            type: string
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/searchTarget'
        - $ref: '#/components/parameters/sort'
      callbacks:
        'searchTarget === search-index':
          $ref: '#/components/callbacks/searchIndex'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                    example: 1
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/VideoPlaylist'
        '500':
          description: search index unavailable

  /blocklist/status:
    get:
      tags:
        - Account Blocks
        - Server Blocks
      summary: Get block status of accounts/hosts
      parameters:
        -
          name: 'accounts'
          in: query
          description: 'Check if these accounts are blocked'
          example: [ 'goofy@example.com', 'donald@example.com' ]
          schema:
            type: array
            items:
              type: string
        -
          name: 'hosts'
          in: query
          description: 'Check if these hosts are blocked'
          example: [ 'example.com' ]
          schema:
            type: array
            items:
              type: string
      responses:
        '200':
          description: successful operation
          content:
            'application/json':
              schema:
                $ref: '#/components/schemas/BlockStatus'

  /server/blocklist/accounts:
    get:
      tags:
        - Account Blocks
      summary: List account blocks
      security:
        - OAuth2:
          - admin
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
    post:
      tags:
        - Account Blocks
      summary: Block an account
      security:
        - OAuth2:
          - admin
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                accountName:
                  type: string
                  example: chocobozzz@example.org
                  description: account to block, in the form `username@domain`
              required:
                - accountName
      responses:
        '200':
          description: successful operation
        '409':
          description: self-blocking forbidden

  '/server/blocklist/accounts/{accountName}':
    delete:
      tags:
        - Account Blocks
      summary: Unblock an account by its handle
      security:
        - OAuth2:
          - admin
      parameters:
        - name: accountName
          in: path
          required: true
          description: account to unblock, in the form `username@domain`
          schema:
            type: string
      responses:
        '201':
          description: successful operation
        '404':
          description: account or account block does not exist

  /server/blocklist/servers:
    get:
      tags:
        - Server Blocks
      summary: List server blocks
      security:
        - OAuth2:
          - admin
      parameters:
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
    post:
      tags:
        - Server Blocks
      summary: Block a server
      security:
        - OAuth2:
          - admin
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                host:
                  type: string
                  format: hostname
                  description: server domain to block
              required:
                - host
      responses:
        '204':
          description: successful operation
        '409':
          description: self-blocking forbidden

  '/server/blocklist/servers/{host}':
    delete:
      tags:
        - Server Blocks
      summary: Unblock a server by its domain
      security:
        - OAuth2:
          - admin
      parameters:
        - name: host
          in: path
          required: true
          description: server domain to unblock
          schema:
            type: string
            format: hostname
      responses:
        '204':
          description: successful operation
        '404':
          description: account block does not exist

  /server/redundancy/{host}:
    put:
      tags:
        - Instance Redundancy
      summary: Update a server redundancy policy
      security:
        - OAuth2:
          - admin
      parameters:
        - name: host
          in: path
          required: true
          description: server domain to mirror
          schema:
            type: string
            format: hostname
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                redundancyAllowed:
                  type: boolean
                  description: allow mirroring of the host's local videos
              required:
                - redundancyAllowed
      responses:
        '204':
          description: successful operation
        '404':
          description: server is not already known

  /server/redundancy/videos:
    get:
      tags:
        - Video Mirroring
      summary: List videos being mirrored
      operationId: getMirroredVideos
      security:
        - OAuth2:
          - admin
      parameters:
        - name: target
          in: query
          required: true
          description: direction of the mirror
          schema:
            type: string
            enum:
              - my-videos
              - remote-videos
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/videoRedundanciesSort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/VideoRedundancy'
    post:
      tags:
        - Video Mirroring
      summary: Mirror a video
      operationId: putMirroredVideo
      security:
        - OAuth2:
          - admin
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                videoId:
                  $ref: '#/components/schemas/Video/properties/id'
              required:
                - videoId
      responses:
        '204':
          description: successful operation
        '400':
          description: cannot mirror a local video
        '404':
          description: video does not exist
        '409':
          description: video is already mirrored

  /server/redundancy/videos/{redundancyId}:
    delete:
      tags:
        - Video Mirroring
      summary: Delete a mirror done on a video
      operationId: delMirroredVideo
      security:
        - OAuth2:
          - admin
      parameters:
        - name: redundancyId
          in: path
          required: true
          description: id of an existing redundancy on a video
          schema:
            type: string
      responses:
        '204':
          description: successful operation
        '404':
          description: video redundancy not found

  '/feeds/video-comments.{format}':
    get:
      tags:
        - Feeds
      summary: List comments on videos
      operationId: getSyndicatedComments
      parameters:
        - name: format
          in: path
          required: true
          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
          schema:
            type: string
            enum:
              - xml
              - rss
              - rss2
              - atom
              - atom1
              - json
              - json1
        - name: videoId
          in: query
          description: 'limit listing to a specific video'
          schema:
            type: string
        - name: accountId
          in: query
          description: 'limit listing to a specific account'
          schema:
            type: string
        - name: accountName
          in: query
          description: 'limit listing to a specific account'
          schema:
            type: string
        - name: videoChannelId
          in: query
          description: 'limit listing to a specific video channel'
          schema:
            type: string
        - name: videoChannelName
          in: query
          description: 'limit listing to a specific video channel'
          schema:
            type: string
      responses:
        '204':
          description: successful operation
          headers:
            Cache-Control:
              schema:
                type: string
                default: 'max-age=900' # 15 min cache
          content:
            application/xml:
              schema:
                $ref: '#/components/schemas/VideoCommentsForXML'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/video-comments.xml?filter=local
            application/rss+xml:
              schema:
                $ref: '#/components/schemas/VideoCommentsForXML'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/video-comments.rss?filter=local
            text/xml:
              schema:
                $ref: '#/components/schemas/VideoCommentsForXML'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/video-comments.xml?filter=local
            application/atom+xml:
              schema:
                $ref: '#/components/schemas/VideoCommentsForXML'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/video-comments.atom?filter=local
            application/json:
              schema:
                type: object
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/video-comments.json?filter=local
        '400':
          x-summary: field inconsistencies
          description: >
            Arises when:
              - videoId filter is mixed with a channel filter
        '404':
          description: video, video channel or account not found
        '406':
          description: accept header unsupported

  '/feeds/videos.{format}':
    get:
      tags:
        - Feeds
      summary: List videos
      operationId: getSyndicatedVideos
      parameters:
        - name: format
          in: path
          required: true
          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
          schema:
            type: string
            enum:
              - xml
              - rss
              - rss2
              - atom
              - atom1
              - json
              - json1
        - name: accountId
          in: query
          description: 'limit listing to a specific account'
          schema:
            type: string
        - name: accountName
          in: query
          description: 'limit listing to a specific account'
          schema:
            type: string
        - name: videoChannelId
          in: query
          description: 'limit listing to a specific video channel'
          schema:
            type: string
        - name: videoChannelName
          in: query
          description: 'limit listing to a specific video channel'
          schema:
            type: string
        - $ref: '#/components/parameters/sort'
        - $ref: '#/components/parameters/nsfw'
        - $ref: '#/components/parameters/isLocal'
        - $ref: '#/components/parameters/include'
        - $ref: '#/components/parameters/privacyOneOf'
        - $ref: '#/components/parameters/hasHLSFiles'
        - $ref: '#/components/parameters/hasWebtorrentFiles'
      responses:
        '204':
          description: successful operation
          headers:
            Cache-Control:
              schema:
                type: string
                default: 'max-age=900' # 15 min cache
          content:
            application/xml:
              schema:
                $ref: '#/components/schemas/VideosForXML'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/videos.xml?filter=local
            application/rss+xml:
              schema:
                $ref: '#/components/schemas/VideosForXML'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/videos.rss?filter=local
            text/xml:
              schema:
                $ref: '#/components/schemas/VideosForXML'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/videos.xml?filter=local
            application/atom+xml:
              schema:
                $ref: '#/components/schemas/VideosForXML'
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/videos.atom?filter=local
            application/json:
              schema:
                type: object
              examples:
                nightly:
                  externalValue: https://peertube2.cpy.re/feeds/videos.json?filter=local
        '404':
          description: video channel or account not found
        '406':
          description: accept header unsupported

  '/feeds/subscriptions.{format}':
    get:
      tags:
        - Feeds
        - Account
      summary: List videos of subscriptions tied to a token
      operationId: getSyndicatedSubscriptionVideos
      parameters:
        - name: format
          in: path
          required: true
          description: 'format expected (we focus on making `rss` the most featureful ; it serves [Media RSS](https://www.rssboard.org/media-rss))'
          schema:
            type: string
            enum:
              - xml
              - rss
              - rss2
              - atom
              - atom1
              - json
              - json1
        - name: accountId
          in: query
          description: limit listing to a specific account
          schema:
            type: string
          required: true
        - name: token
          in: query
          description: private token allowing access
          schema:
            type: string
          required: true
        - $ref: '#/components/parameters/sort'
        - $ref: '#/components/parameters/nsfw'
        - $ref: '#/components/parameters/isLocal'
        - $ref: '#/components/parameters/include'
        - $ref: '#/components/parameters/privacyOneOf'
        - $ref: '#/components/parameters/hasHLSFiles'
        - $ref: '#/components/parameters/hasWebtorrentFiles'
      responses:
        '204':
          description: successful operation
          headers:
            Cache-Control:
              schema:
                type: string
                default: 'max-age=900' # 15 min cache
          content:
            application/xml:
              schema:
                $ref: '#/components/schemas/VideosForXML'
            application/rss+xml:
              schema:
                $ref: '#/components/schemas/VideosForXML'
            text/xml:
              schema:
                $ref: '#/components/schemas/VideosForXML'
            application/atom+xml:
              schema:
                $ref: '#/components/schemas/VideosForXML'
            application/json:
              schema:
                type: object
        '406':
          description: accept header unsupported

  /plugins:
    get:
      tags:
        - Plugins
      summary: List plugins
      operationId: getPlugins
      security:
        - OAuth2:
          - admin
      parameters:
        - name: pluginType
          in: query
          schema:
            type: integer
        - name: uninstalled
          in: query
          schema:
            type: boolean
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PluginResponse'

  /plugins/available:
    get:
      tags:
        - Plugins
      summary: List available plugins
      operationId: getAvailablePlugins
      security:
        - OAuth2:
          - admin
      parameters:
        - name: search
          in: query
          schema:
            type: string
        - name: pluginType
          in: query
          schema:
            type: integer
        - name: currentPeerTubeEngine
          in: query
          schema:
            type: string
        - $ref: '#/components/parameters/start'
        - $ref: '#/components/parameters/count'
        - $ref: '#/components/parameters/sort'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PluginResponse'
        '503':
          description: plugin index unavailable

  /plugins/install:
    post:
      tags:
        - Plugins
      summary: Install a plugin
      operationId: addPlugin
      security:
        - OAuth2:
          - admin
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - type: object
                  properties:
                    npmName:
                      type: string
                      example: peertube-plugin-auth-ldap
                  required:
                    - npmName
                  additionalProperties: false
                - type: object
                  properties:
                    path:
                      type: string
                  required:
                    - path
                  additionalProperties: false
      responses:
        '204':
          description: successful operation
        '400':
          description: should have either `npmName` or `path` set

  /plugins/update:
    post:
      tags:
        - Plugins
      summary: Update a plugin
      operationId: updatePlugin
      security:
        - OAuth2:
          - admin
      requestBody:
        content:
          application/json:
            schema:
              oneOf:
                - type: object
                  properties:
                    npmName:
                      type: string
                      example: peertube-plugin-auth-ldap
                  required:
                    - npmName
                  additionalProperties: false
                - type: object
                  properties:
                    path:
                      type: string
                  required:
                    - path
                  additionalProperties: false
      responses:
        '204':
          description: successful operation
        '400':
          description: should have either `npmName` or `path` set
        '404':
          description: existing plugin not found

  /plugins/uninstall:
    post:
      tags:
        - Plugins
      summary: Uninstall a plugin
      operationId: uninstallPlugin
      security:
        - OAuth2:
          - admin
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                npmName:
                  type: string
                  description: name of the plugin/theme in its package.json
                  example: peertube-plugin-auth-ldap
              required:
                - npmName
      responses:
        '204':
          description: successful operation
        '404':
          description: existing plugin not found

  /plugins/{npmName}:
    get:
      tags:
        - Plugins
      summary: Get a plugin
      operationId: getPlugin
      security:
        - OAuth2:
          - admin
      parameters:
        - $ref: '#/components/parameters/npmName'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Plugin'
        '404':
          description: plugin not found

  /plugins/{npmName}/settings:
    put:
      tags:
        - Plugins
      summary: Set a plugin's settings
      security:
        - OAuth2:
          - admin
      parameters:
        - $ref: '#/components/parameters/npmName'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                settings:
                  type: object
                  additionalProperties: true
      responses:
        '204':
          description: successful operation
        '404':
          description: plugin not found

  /plugins/{npmName}/public-settings:
    get:
      tags:
        - Plugins
      summary: Get a plugin's public settings
      parameters:
        - $ref: '#/components/parameters/npmName'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '404':
          description: plugin not found

  /plugins/{npmName}/registered-settings:
    get:
      tags:
        - Plugins
      summary: Get a plugin's registered settings
      security:
        - OAuth2:
          - admin
      parameters:
        - $ref: '#/components/parameters/npmName'
      responses:
        '200':
          description: successful operation
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '404':
          description: plugin not found

servers:
  - url: 'https://peertube2.cpy.re/api/v1'
    description: Live Test Server (live data - latest nightly version)
  - url: 'https://peertube3.cpy.re/api/v1'
    description: Live Test Server (live data - latest RC version)
  - url: 'https://peertube.cpy.re/api/v1'
    description: Live Test Server (live data - stable version)
components:
  parameters:
    start:
      name: start
      in: query
      required: false
      description: Offset used to paginate results
      schema:
        type: integer
        minimum: 0
    count:
      name: count
      in: query
      required: false
      description: "Number of items to return"
      schema:
        type: integer
        default: 15
        maximum: 100
        minimum: 1
    sort:
      name: sort
      in: query
      required: false
      description: Sort column
      schema:
        type: string
        example: -createdAt
    search:
      name: search
      in: query
      required: false
      description: Plain text search, applied to various parts of the model depending on endpoint
      schema:
        type: string
    searchTarget:
      name: searchTarget
      in: query
      required: false
      description: >
        If the administrator enabled search index support, you can override the default search target.


        **Warning**: If you choose to make an index search, PeerTube will get results from a third party service.
        It means the instance may not yet know the objects you fetched. If you want to load video/channel information:
          * If the current user has the ability to make a remote URI search (this information is available in the config endpoint),
          then reuse the search API to make a search using the object URI so PeerTube instance fetches the remote object and fill its database.
          After that, you can use the classic REST API endpoints to fetch the complete object or interact with it
          * If the current user doesn't have the ability to make a remote URI search, then redirect the user on the origin instance or fetch
          the data from the origin instance API
      schema:
        type: string
        enum:
          - 'local'
          - 'search-index'
    videosSort:
      name: sort
      in: query
      required: false
      description: Sort videos by criteria
      schema:
        type: string
        enum:
        - name
        - -duration
        - -createdAt
        - -publishedAt
        - -views
        - -likes
        - -trending
        - -hot
    videosSearchSort:
      name: sort
      in: query
      required: false
      description: Sort videos by criteria
      schema:
        type: string
        enum:
        - name
        - -duration
        - -createdAt
        - -publishedAt
        - -views
        - -likes
        - -match
    commentsSort:
      name: sort
      in: query
      required: false
      description: Sort comments by criteria
      schema:
        type: string
        enum:
        - -createdAt
        - -totalReplies
    blacklistsSort:
      name: sort
      in: query
      required: false
      description: Sort blocklists by criteria
      schema:
        type: string
        enum:
        - -id
        - name
        - -duration
        - -views
        - -likes
        - -dislikes
        - -uuid
        - -createdAt
    usersSearch:
      name: search
      in: query
      required: false
      description: Plain text search that will match with user usernames or emails
      schema:
        type: string
    usersBlocked:
      name: blocked
      in: query
      required: false
      description: Filter results down to (un)banned users
      schema:
        type: boolean
    usersSort:
      name: sort
      in: query
      required: false
      description: Sort users by criteria
      schema:
        type: string
        enum:
        - -id
        - -username
        - -createdAt
    abusesSort:
      name: sort
      in: query
      required: false
      description: Sort abuses by criteria
      schema:
        type: string
        enum:
        - -id
        - -createdAt
        - -state
    videoRedundanciesSort:
      name: sort
      in: query
      required: false
      description: Sort abuses by criteria
      schema:
        type: string
        enum:
        - name
    followersSort:
      name: sort
      in: query
      required: false
      description: Sort followers by criteria
      schema:
        type: string
        enum:
        - createdAt
    name:
      name: name
      in: path
      required: true
      description: The username or handle of the account
      schema:
        type: string
        example: chocobozzz | chocobozzz@example.org
    id:
      name: id
      in: path
      required: true
      description: Entity id
      schema:
        $ref: '#/components/schemas/id'
    idOrUUID:
      name: id
      in: path
      required: true
      description: The object id, uuid or short uuid
      schema:
        oneOf:
          - $ref: '#/components/schemas/id'
          - $ref: '#/components/schemas/UUIDv4'
          - $ref: '#/components/schemas/shortUUID'
    playlistId:
      name: playlistId
      in: path
      required: true
      description: Playlist id
      schema:
        $ref: '#/components/schemas/VideoPlaylist/properties/id'
    playlistElementId:
      name: playlistElementId
      in: path
      required: true
      description: Playlist element id
      schema:
        $ref: '#/components/schemas/id'
    abuseId:
      name: abuseId
      in: path
      required: true
      description: Abuse id
      schema:
        $ref: '#/components/schemas/Abuse/properties/id'
    abuseMessageId:
      name: abuseMessageId
      in: path
      required: true
      description: Abuse message id
      schema:
        $ref: '#/components/schemas/AbuseMessage/properties/id'
    captionLanguage:
      name: captionLanguage
      in: path
      required: true
      description: The caption language
      schema:
        $ref: '#/components/schemas/VideoLanguageSet'
    channelHandle:
      name: channelHandle
      in: path
      required: true
      description: The video channel handle
      schema:
        type: string
        example: my_username | my_username@example.com
    subscriptionHandle:
      name: subscriptionHandle
      in: path
      required: true
      description: The subscription handle
      schema:
        type: string
        example: my_username | my_username@example.com
    threadId:
      name: threadId
      in: path
      required: true
      description: The thread id (root comment id)
      schema:
        type: integer
    commentId:
      name: commentId
      in: path
      required: true
      description: The comment id
      schema:
        $ref: '#/components/schemas/VideoComment/properties/id'
    isLive:
      name: isLive
      in: query
      required: false
      description: whether or not the video is a live
      schema:
        type: boolean
    categoryOneOf:
      name: categoryOneOf
      in: query
      required: false
      description: category id of the video (see [/videos/categories](#operation/getCategories))
      schema:
        oneOf:
        - $ref: '#/components/schemas/VideoCategorySet'
        - type: array
          items:
            $ref: '#/components/schemas/VideoCategorySet'
      style: form
      explode: false
    tagsOneOf:
      name: tagsOneOf
      in: query
      required: false
      description: tag(s) of the video
      schema:
        oneOf:
        - type: string
        - type: array
          maxItems: 5
          items:
            type: string
      style: form
      explode: false
    tagsAllOf:
      name: tagsAllOf
      in: query
      required: false
      description: tag(s) of the video, where all should be present in the video
      schema:
        oneOf:
        - type: string
        - type: array
          items:
            type: string
      style: form
      explode: false
    languageOneOf:
      name: languageOneOf
      in: query
      required: false
      description: language id of the video (see [/videos/languages](#operation/getLanguages)). Use `_unknown` to filter on videos that don't have a video language
      schema:
        oneOf:
        - $ref: '#/components/schemas/VideoLanguageSet'
        - type: array
          items:
            $ref: '#/components/schemas/VideoLanguageSet'
      style: form
      explode: false
    licenceOneOf:
      name: licenceOneOf
      in: query
      required: false
      description: licence id of the video (see [/videos/licences](#operation/getLicences))
      schema:
        oneOf:
        - $ref: '#/components/schemas/VideoLicenceSet'
        - type: array
          items:
            $ref: '#/components/schemas/VideoLicenceSet'
      style: form
      explode: false
    skipCount:
      name: skipCount
      in: query
      required: false
      description: if you don't need the `total` in the response
      schema:
        type: string
        enum:
          - 'true'
          - 'false'
        default: 'false'
    nsfw:
      name: nsfw
      in: query
      required: false
      description: whether to include nsfw videos, if any
      schema:
        type: string
        enum:
        - 'true'
        - 'false'
    isLocal:
      name: isLocal
      in: query
      required: false
      schema:
        type: boolean
      description: '**PeerTube >= 4.0** Display only local or remote videos'
    hasHLSFiles:
      name: hasHLSFiles
      in: query
      required: false
      schema:
        type: boolean
      description: '**PeerTube >= 4.0** Display only videos that have HLS files'
    hasWebtorrentFiles:
      name: hasWebtorrentFiles
      in: query
      required: false
      schema:
        type: boolean
      description: '**PeerTube >= 4.0** Display only videos that have WebTorrent files'
    privacyOneOf:
      name: privacyOneOf
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/VideoPrivacySet'
      description: '**PeerTube >= 4.0** Display only videos in this specific privacy/privacies'
    include:
      name: include
      in: query
      required: false
      schema:
        type: integer
        enum:
        - 0
        - 1
        - 2
        - 4
        - 8
      description: >
        **PeerTube >= 4.0** Include additional videos in results (can be combined using bitwise or operator)

        - `0` NONE

        - `1` NOT_PUBLISHED_STATE

        - `2` BLACKLISTED

        - `4` BLOCKED_OWNER

        - `8` FILES
    subscriptionsUris:
      name: uris
      in: query
      required: true
      description: list of uris to check if each is part of the user subscriptions
      schema:
        type: array
        items:
          type: string
          format: uri
    npmName:
      name: npmName
      in: path
      required: true
      description: name of the plugin/theme on npmjs.com or in its package.json
      schema:
        type: string
        example: peertube-plugin-auth-ldap
    jobType:
      name: jobType
      in: query
      required: false
      description: job type
      schema:
        type: string
        enum:
          - activitypub-follow
          - activitypub-http-broadcast
          - activitypub-http-fetcher
          - activitypub-http-unicast
          - email
          - video-transcoding
          - video-file-import
          - video-import
          - videos-views-stats
          - activitypub-refresher
          - video-redundancy
          - video-live-ending
    followState:
      name: state
      in: query
      schema:
        type: string
        enum:
          - pending
          - accepted
    actorType:
      name: actorType
      in: query
      schema:
        type: string
        enum:
          - Person
          - Application
          - Group
          - Service
          - Organization
  securitySchemes:
    OAuth2:
      description: |
        Authenticating via OAuth requires the following steps:
        - Have an activated account
        - [Generate] an access token for that account at `/api/v1/users/token`.
        - Make requests with the *Authorization: Bearer <token\>* header
        - Profit, depending on the role assigned to the account

        Note that the __access token is valid for 1 day__ and is given
        along with a __refresh token valid for 2 weeks__.

        [Generate]: https://docs.joinpeertube.org/api-rest-getting-started
      type: oauth2
      flows:
        password:
          tokenUrl: /api/v1/users/token
          scopes:
            admin: Admin scope
            moderator: Moderator scope
            user: User scope
  schemas:
    # Resuable core properties
    id:
      type: integer
      minimum: 1
      example: 42
    UUIDv4:
      type: string
      format: uuid
      example: 9c9de5e8-0a1e-484a-b099-e80766180a6d
      pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
      minLength: 36
      maxLength: 36
    shortUUID:
      type: string
      description: translation of a uuid v4 with a bigger alphabet to have a shorter uuid
      example: 2y84q2MQUMWPbiEcxNXMgC
    username:
      type: string
      description: immutable name of the user, used to find or mention its actor
      example: chocobozzz
      pattern: '/^[a-z0-9._]+$/'
      minLength: 1
      maxLength: 50
    usernameChannel:
      type: string
      description: immutable name of the channel, used to interact with its actor
      example: framasoft_videos
      pattern: '/^[a-zA-Z0-9\\-_.:]+$/'
      minLength: 1
      maxLength: 50
    password:
      type: string
      format: password
      minLength: 6
      maxLength: 255

    VideoCategorySet:
      type: integer
      description: category id of the video (see [/videos/categories](#operation/getCategories))
      example: 15
    VideoConstantNumber-Category:
      properties:
        id:
          $ref: '#/components/schemas/VideoCategorySet'
        label:
          type: string
          example: Science & Technology

    VideoLicenceSet:
      type: integer
      description: licence id of the video (see [/videos/licences](#operation/getLicences))
      example: 2
    VideoConstantNumber-Licence:
      properties:
        id:
          $ref: '#/components/schemas/VideoLicenceSet'
        label:
          type: string
          example: Attribution - Share Alike

    VideoLanguageSet:
      type: string
      description: language id of the video (see [/videos/languages](#operation/getLanguages))
      example: en
    VideoConstantString-Language:
      properties:
        id:
          $ref: '#/components/schemas/VideoLanguageSet'
        label:
          type: string
          example: English

    VideoPlaylistPrivacySet:
      type: integer
      enum:
        - 1
        - 2
        - 3
      description: Video playlist privacy policy (see [/video-playlists/privacies])
    VideoPlaylistPrivacyConstant:
      properties:
        id:
          $ref: '#/components/schemas/VideoPlaylistPrivacySet'
        label:
          type: string

    VideoPlaylistTypeSet:
      type: integer
      enum:
        - 1
        - 2
      description: The video playlist type (Regular = `1`, Watch Later = `2`)
    VideoPlaylistTypeConstant:
      properties:
        id:
          $ref: '#/components/schemas/VideoPlaylistTypeSet'
        label:
          type: string

    VideoPrivacySet:
      type: integer
      enum:
        - 1
        - 2
        - 3
        - 4
      description: privacy id of the video (see [/videos/privacies](#operation/getPrivacyPolicies))
    VideoPrivacyConstant:
      properties:
        id:
          $ref: '#/components/schemas/VideoPrivacySet'
        label:
          type: string

    BlockStatus:
      properties:
        accounts:
          type: object
          additionalProperties:
            x-additionalPropertiesName: account
            type: object
            properties:
              blockedByServer:
                type: boolean
              blockedByUser:
                type: boolean
        hosts:
          type: object
          additionalProperties:
            x-additionalPropertiesName: host
            type: object
            properties:
              blockedByServer:
                type: boolean
              blockedByUser:
                type: boolean

    NSFWPolicy:
      type: string
      enum:
        - display
        - blur
        - do_not_list

    UserRole:
      type: integer
      enum:
        - 0
        - 1
        - 2
      description: 'The user role (Admin = `0`, Moderator = `1`, User = `2`)'
      example: 2
    UserAdminFlags:
      type: integer
      enum:
        - 0
        - 1
      description: 'Admin flags for the user (None = `0`, Bypass video blocklist = `1`)'
      example: 1

    VideoStateConstant:
      properties:
        id:
          type: integer
          enum:
            - 1
            - 2
            - 3
          description: 'The video state (Published = `1`, to transcode = `2`, to import = `3`)'
        label:
          type: string

    AbuseStateSet:
      type: integer
      enum:
        - 1
        - 2
        - 3
      description: 'The abuse state (Pending = `1`, Rejected = `2`, Accepted = `3`)'
    AbuseStateConstant:
      properties:
        id:
          $ref: '#/components/schemas/AbuseStateSet'
        label:
          type: string
    AbusePredefinedReasons:
      type: array
      items:
        type: string
        enum:
        - violentOrAbusive
        - hatefulOrAbusive
        - spamOrMisleading
        - privacy
        - rights
        - serverRules
        - thumbnails
        - captions
      example: [spamOrMisleading]

    VideoResolutionSet:
      type: integer
      description: |
        Video resolution (`0`, `240`, `360`, `720`, `1080`, `1440` or `2160`)

        `0` is used as a special value for stillimage videos dedicated to audio, a.k.a. audio-only videos.
      example: 240
    VideoResolutionConstant:
      description: resolutions and their labels for the video
      properties:
        id:
          $ref: '#/components/schemas/VideoResolutionSet'
        label:
          type: string
          example: 240p
    VideoScheduledUpdate:
      properties:
        privacy:
          $ref: '#/components/schemas/VideoPrivacySet'
        updateAt:
          type: string
          format: date
          description: When to update the video
      required:
        - updateAt
    AccountSummary:
      properties:
        id:
          type: integer
        name:
          type: string
        displayName:
          type: string
        url:
          type: string
          format: url
        host:
          type: string
          format: hostname
        avatar:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ActorImage'
    VideoChannelSummary:
      properties:
        id:
          $ref: '#/components/schemas/id'
        name:
          type: string
        displayName:
          type: string
        url:
          type: string
          format: url
        host:
          type: string
          format: hostname
        avatar:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ActorImage'
    PlaylistElement:
      properties:
        position:
          type: integer
        startTimestamp:
          type: integer
          format: seconds
        stopTimestamp:
          type: integer
          format: seconds
        video:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/Video'
    VideoFile:
      readOnly: true
      properties:
        magnetUri:
          type: string
          format: uri
          description: magnet URI allowing to resolve the video via BitTorrent without a metainfo file
          pattern: /magnet:\?xt=urn:[a-z0-9]+:[a-z0-9]{32}/i
        resolution:
          $ref: '#/components/schemas/VideoResolutionConstant'
        size:
          type: integer
          description: Video file size in bytes
        torrentUrl:
          type: string
          description: Direct URL of the torrent file
          format: url
        torrentDownloadUrl:
          type: string
          description: URL endpoint that transfers the torrent file as an attachment (so that the browser opens a download dialog)
          format: url
        fileUrl:
          type: string
          description: Direct URL of the video
          format: url
        fileDownloadUrl:
          type: string
          description: URL endpoint that transfers the video file as an attachment (so that the browser opens a download dialog)
          format: url
        fps:
          type: number
          description: Frames per second of the video file
        metadataUrl:
          type: string
          format: url
          description: URL dereferencing the output of ffprobe on the file
    VideoStreamingPlaylists:
      allOf:
        - type: object
          properties:
            id:
              $ref: '#/components/schemas/id'
            type:
              type: integer
              enum:
                - 1
              description: |
                Playlist type:
                - `1`: HLS
        - $ref: '#/components/schemas/VideoStreamingPlaylists-HLS'
    VideoStreamingPlaylists-HLS:
      properties:
        playlistUrl:
          type: string
          format: url
        segmentsSha256Url:
          type: string
          format: url
        files:
          type: array
          description: |
            Video files associated to this playlist.

            The difference with the root `files` property is that these files are fragmented, so they can be used in this streaming playlist (HLS, etc.)
          items:
            $ref: '#/components/schemas/VideoFile'
        redundancies:
          type: array
          items:
            type: object
            properties:
              baseUrl:
                type: string
                format: url
    VideoInfo:
      properties:
        id:
          $ref: '#/components/schemas/Video/properties/id'
        uuid:
          $ref: '#/components/schemas/Video/properties/uuid'
        name:
          $ref: '#/components/schemas/Video/properties/name'
    Video:
      properties:
        id:
          description: object id for the video
          allOf:
            - $ref: '#/components/schemas/id'
        uuid:
          description: universal identifier for the video, that can be used across instances
          allOf:
            - $ref: '#/components/schemas/UUIDv4'
        shortUUID:
          allOf:
            - $ref: '#/components/schemas/shortUUID'
        isLive:
          type: boolean
        createdAt:
          type: string
          format: date-time
          example: 2017-10-01T10:52:46.396Z
          description: time at which the video object was first drafted
        publishedAt:
          type: string
          format: date-time
          example: 2018-10-01T10:52:46.396Z
          description: time at which the video was marked as ready for playback (with restrictions depending on `privacy`). Usually set after a `state` evolution.
        updatedAt:
          type: string
          format: date-time
          example: 2021-05-04T08:01:01.502Z
          description: last time the video's metadata was modified
        originallyPublishedAt:
          type: string
          format: date-time
          example: 2010-10-01T10:52:46.396Z
          description: used to represent a date of first publication, prior to the practical publication date of `publishedAt`
        category:
          allOf:
            - $ref: '#/components/schemas/VideoConstantNumber-Category'
          description: category in which the video is classified
        licence:
          allOf:
            - $ref: '#/components/schemas/VideoConstantNumber-Licence'
          description: licence under which the video is distributed
        language:
          allOf:
            - $ref: '#/components/schemas/VideoConstantString-Language'
          description: main language used in the video
        privacy:
          allOf:
            - $ref: '#/components/schemas/VideoPrivacyConstant'
          description: privacy policy used to distribute the video
        description:
          type: string
          example: |
            **[Want to help to translate this video?](https://weblate.framasoft.org/projects/what-is-peertube-video/)**\r\n\r\n
            **Take back the control of your videos! [#JoinPeertube](https://joinpeertube.org)**\r\n*A decentralized video hosting network, based on fr...
          minLength: 3
          maxLength: 250
          description: |
            truncated description of the video, written in Markdown.
            Resolve `descriptionPath` to get the full description of maximum `10000` characters.
        duration:
          type: integer
          example: 1419
          format: seconds
          description: duration of the video in seconds
        isLocal:
          type: boolean
        name:
          type: string
          description: title of the video
          example: What is PeerTube?
          minLength: 3
          maxLength: 120
        thumbnailPath:
          type: string
          example: /static/thumbnails/a65bc12f-9383-462e-81ae-8207e8b434ee.jpg
        previewPath:
          type: string
          example: /lazy-static/previews/a65bc12f-9383-462e-81ae-8207e8b434ee.jpg
        embedPath:
          type: string
          example: /videos/embed/a65bc12f-9383-462e-81ae-8207e8b434ee
        views:
          type: integer
          example: 1337
        likes:
          type: integer
          example: 42
        dislikes:
          type: integer
          example: 7
        nsfw:
          type: boolean
        waitTranscoding:
          type: boolean
          nullable: true
        state:
          allOf:
            - $ref: '#/components/schemas/VideoStateConstant'
          description: represents the internal state of the video processing within the PeerTube instance
        scheduledUpdate:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/VideoScheduledUpdate'
        blacklisted:
          nullable: true
          type: boolean
        blacklistedReason:
          nullable: true
          type: string
        account:
          $ref: '#/components/schemas/AccountSummary'
        channel:
          $ref: '#/components/schemas/VideoChannelSummary'
        userHistory:
          nullable: true
          type: object
          properties:
            currentTime:
              type: integer
    VideoDetails:
      allOf:
        - $ref: '#/components/schemas/Video'
        - type: object
          properties:
            viewers:
              type: integer
              description: If the video is a live, you have the amount of current viewers
            descriptionPath:
              type: string
              example: /api/v1/videos/9c9de5e8-0a1e-484a-b099-e80766180a6d/description
              description: path at which to get the full description of maximum `10000` characters
            support:
              type: string
              description: A text tell the audience how to support the video creator
              example: Please support our work on https://soutenir.framasoft.org/en/ <3
              minLength: 3
              maxLength: 1000
            channel:
              $ref: '#/components/schemas/VideoChannel'
            account:
              $ref: '#/components/schemas/Account'
            tags:
              example: [flowers, gardening]
              type: array
              minItems: 1
              maxItems: 5
              items:
                type: string
                minLength: 2
                maxLength: 30
            commentsEnabled:
              type: boolean
            downloadEnabled:
              type: boolean
            trackerUrls:
              type: array
              items:
                type: string
                format: url
              example:
                - https://peertube2.cpy.re/tracker/announce
                - wss://peertube2.cpy.re/tracker/socket
            files:
              type: array
              items:
                $ref: '#/components/schemas/VideoFile'
              description: |
                WebTorrent/raw video files. If WebTorrent is disabled on the server:

                - field will be empty
                - video files will be found in `streamingPlaylists[].files` field
            streamingPlaylists:
              type: array
              items:
                $ref: '#/components/schemas/VideoStreamingPlaylists'
              description: |
                HLS playlists/manifest files. If HLS is disabled on the server:

                - field will be empty
                - video files will be found in `files` field
    FileRedundancyInformation:
      properties:
        id:
          $ref: '#/components/schemas/id'
        fileUrl:
          type: string
          format: url
        strategy:
          type: string
          enum:
            - manual
            - most-views
            - trending
            - recently-added
        size:
          type: integer
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        expiresOn:
          type: string
          format: date-time
    VideoRedundancy:
      properties:
        id:
          $ref: '#/components/schemas/id'
        name:
          type: string
        url:
          type: string
          format: url
        uuid:
          $ref: '#/components/schemas/UUIDv4'
        redundancies:
          type: object
          properties:
            files:
              type: array
              items:
                $ref: '#/components/schemas/FileRedundancyInformation'
            streamingPlaylists:
              type: array
              items:
                $ref: '#/components/schemas/FileRedundancyInformation'
    VideoImportStateConstant:
      properties:
        id:
          type: integer
          enum:
            - 1
            - 2
            - 3
          description: 'The video import state (Pending = `1`, Success = `2`, Failed = `3`)'
        label:
          type: string
          example: Pending
    VideoCreateImport:
      allOf:
        - type: object
          additionalProperties: false
          oneOf:
            - properties:
                targetUrl:
                  $ref: '#/components/schemas/VideoImport/properties/targetUrl'
              required: [targetUrl]
            - properties:
                magnetUri:
                  $ref: '#/components/schemas/VideoImport/properties/magnetUri'
              required: [magnetUri]
            - properties:
                torrentfile:
                  $ref: '#/components/schemas/VideoImport/properties/torrentfile'
              required: [torrentfile]
        - $ref: '#/components/schemas/VideoUploadRequestCommon'
      required:
        - channelId
        - name
    VideoImport:
      properties:
        id:
          readOnly: true
          allOf:
            - $ref: '#/components/schemas/id'
        targetUrl:
          type: string
          format: url
          description: remote URL where to find the import's source video
          example: https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d
        magnetUri:
          type: string
          format: uri
          description: magnet URI allowing to resolve the import's source video
          pattern: /magnet:\?xt=urn:[a-z0-9]+:[a-z0-9]{32}/i
        torrentfile:
          writeOnly: true
          type: string
          format: binary
          description: Torrent file containing only the video file
        torrentName:
          readOnly: true
          type: string
        state:
          readOnly: true
          allOf:
            - $ref: '#/components/schemas/VideoImportStateConstant'
        error:
          readOnly: true
          type: string
        createdAt:
          readOnly: true
          type: string
          format: date-time
        updatedAt:
          readOnly: true
          type: string
          format: date-time
        video:
          readOnly: true
          nullable: true
          allOf:
            - $ref: '#/components/schemas/Video'
    VideoImportsList:
      properties:
        total:
          type: integer
          example: 1
        data:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/VideoImport'
    Abuse:
      properties:
        id:
          $ref: '#/components/schemas/id'
        reason:
          type: string
          example: The video is a spam
          minLength: 2
          maxLength: 3000
        predefinedReasons:
          $ref: '#/components/schemas/AbusePredefinedReasons'
        reporterAccount:
          $ref: '#/components/schemas/Account'
        state:
          $ref: '#/components/schemas/AbuseStateConstant'
        moderationComment:
          type: string
          example: Decided to ban the server since it spams us regularly
          minLength: 2
          maxLength: 3000
        video:
          $ref: '#/components/schemas/VideoInfo'
        createdAt:
          type: string
          format: date-time
    AbuseMessage:
      properties:
        id:
          $ref: '#/components/schemas/id'
        message:
          type: string
          minLength: 2
          maxLength: 3000
        byModerator:
          type: boolean
        createdAt:
          type: string
          format: date-time
        account:
          $ref: '#/components/schemas/AccountSummary'
    VideoBlacklist:
      properties:
        id:
          $ref: '#/components/schemas/id'
        videoId:
          $ref: '#/components/schemas/Video/properties/id'
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        name:
          type: string
          minLength: 3
          maxLength: 120
        uuid:
          $ref: '#/components/schemas/UUIDv4'
        description:
          type: string
          minLength: 3
          maxLength: 10000
        duration:
          type: integer
        views:
          type: integer
        likes:
          type: integer
        dislikes:
          type: integer
        nsfw:
          type: boolean
    VideoPlaylist:
      properties:
        id:
          $ref: '#/components/schemas/id'
        uuid:
          $ref: '#/components/schemas/UUIDv4'
        shortUUID:
          allOf:
            - $ref: '#/components/schemas/shortUUID'
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        description:
          type: string
          minLength: 3
          maxLength: 1000
        displayName:
          type: string
          minLength: 1
          maxLength: 120
        isLocal:
          type: boolean
        videoLength:
          type: integer
          minimum: 0
        thumbnailPath:
          type: string
        privacy:
          $ref: '#/components/schemas/VideoPlaylistPrivacyConstant'
        type:
          $ref: '#/components/schemas/VideoPlaylistTypeConstant'
        ownerAccount:
          $ref: '#/components/schemas/AccountSummary'
        videoChannel:
          $ref: '#/components/schemas/VideoChannelSummary'
    VideoComment:
      properties:
        id:
          $ref: '#/components/schemas/id'
        url:
          type: string
          format: url
        text:
          type: string
          format: html
          description: Text of the comment
          minLength: 1
          example: This video is wonderful!
        threadId:
          $ref: '#/components/schemas/id'
        inReplyToCommentId:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/id'
        videoId:
          $ref: '#/components/schemas/Video/properties/id'
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        deletedAt:
          nullable: true
          type: string
          format: date-time
        isDeleted:
          type: boolean
          default: false
        totalRepliesFromVideoAuthor:
          type: integer
          minimum: 0
        totalReplies:
          type: integer
          minimum: 0
        account:
          $ref: '#/components/schemas/Account'
    VideoCommentThreadTree:
      properties:
        comment:
          $ref: '#/components/schemas/VideoComment'
        children:
          type: array
          items:
            $ref: '#/components/schemas/VideoCommentThreadTree'
    VideoCaption:
      properties:
        language:
          $ref: '#/components/schemas/VideoConstantString-Language'
        captionPath:
          type: string
    ActorImage:
      properties:
        path:
          type: string
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    ActorInfo:
      properties:
        id:
          $ref: '#/components/schemas/id'
        name:
          type: string
        displayName:
          type: string
        host:
          type: string
          format: hostname
        avatar:
          nullable: true
          type: object
          properties:
            path:
              type: string
    Actor:
      properties:
        id:
          $ref: '#/components/schemas/id'
        url:
          type: string
          format: url
        name:
          description: immutable name of the actor, used to find or mention it
          allOf:
            - $ref: '#/components/schemas/username'
        host:
          type: string
          format: hostname
          description: server on which the actor is resident
        hostRedundancyAllowed:
          type: boolean
          description: whether this actor's host allows redundancy of its videos
        followingCount:
          type: integer
          minimum: 0
          description: number of actors subscribed to by this actor, as seen by this instance
        followersCount:
          type: integer
          minimum: 0
          description: number of followers of this actor, as seen by this instance
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
        avatar:
          $ref: '#/components/schemas/ActorImage'
    Account:
      allOf:
        - $ref: '#/components/schemas/Actor'
        - properties:
            userId:
              description: object id for the user tied to this account
              allOf:
                - $ref: '#/components/schemas/User/properties/id'
            displayName:
              type: string
              description: editable name of the account, displayed in its representations
              minLength: 3
              maxLength: 120
            description:
              type: string
              description: text or bio displayed on the account's profile
    UserWatchingVideo:
      properties:
        currentTime:
          type: integer
          format: seconds
          description: timestamp within the video, in seconds
          example: 5
    ServerConfig:
      properties:
        instance:
          type: object
          properties:
            name:
              type: string
            shortDescription:
              type: string
            defaultClientRoute:
              type: string
            isNSFW:
              type: boolean
            defaultNSFWPolicy:
              type: string
            customizations:
              type: object
              properties:
                javascript:
                  type: string
                css:
                  type: string
        search:
          type: object
          properties:
            remoteUri:
              type: object
              properties:
                users:
                  type: boolean
                anonymous:
                  type: boolean
        plugin:
          type: object
          properties:
            registered:
              type: array
              items:
                type: string
        theme:
          type: object
          properties:
            registered:
              type: array
              items:
                type: string
        email:
          type: object
          properties:
            enabled:
              type: boolean
        contactForm:
          type: object
          properties:
            enabled:
              type: boolean
        serverVersion:
          type: string
        serverCommit:
          type: string
        signup:
          type: object
          properties:
            allowed:
              type: boolean
            allowedForCurrentIP:
              type: boolean
            requiresEmailVerification:
              type: boolean
        transcoding:
          type: object
          properties:
            hls:
              type: object
              properties:
                enabled:
                  type: boolean
            webtorrent:
              type: object
              properties:
                enabled:
                  type: boolean
            enabledResolutions:
              type: array
              items:
                $ref: '#/components/schemas/VideoResolutionSet'
        import:
          type: object
          properties:
            videos:
              type: object
              properties:
                http:
                  type: object
                  properties:
                    enabled:
                      type: boolean
                torrent:
                  type: object
                  properties:
                    enabled:
                      type: boolean
        autoBlacklist:
          type: object
          properties:
            videos:
              type: object
              properties:
                ofUsers:
                  type: object
                  properties:
                    enabled:
                      type: boolean
        avatar:
          type: object
          properties:
            file:
              type: object
              properties:
                size:
                  type: object
                  properties:
                    max:
                      type: integer
            extensions:
              type: array
              items:
                type: string
        video:
          type: object
          properties:
            image:
              type: object
              properties:
                extensions:
                  type: array
                  items:
                    type: string
                size:
                  type: object
                  properties:
                    max:
                      type: integer
            file:
              type: object
              properties:
                extensions:
                  type: array
                  items:
                    type: string
        videoCaption:
          type: object
          properties:
            file:
              type: object
              properties:
                size:
                  type: object
                  properties:
                    max:
                      type: integer
                extensions:
                  type: array
                  items:
                    type: string
        user:
          type: object
          properties:
            videoQuota:
              type: integer
              example: 16810141515
            videoQuotaDaily:
              type: integer
              example: 1681014151
        trending:
          type: object
          properties:
            videos:
              type: object
              properties:
                intervalDays:
                  type: integer
        tracker:
          type: object
          properties:
            enabled:
              type: boolean
        followings:
          type: object
          properties:
            instance:
              type: object
              properties:
                autoFollowIndex:
                  type: object
                  properties:
                    indexUrl:
                      type: string
                      format: url
        homepage:
          type: object
          properties:
            enabled:
              type: boolean

    ServerConfigAbout:
      properties:
        instance:
          type: object
          properties:
            name:
              type: string
            shortDescription:
              type: string
            description:
              type: string
            terms:
              type: string
    ServerConfigCustom:
      properties:
        instance:
          type: object
          properties:
            name:
              type: string
            shortDescription:
              type: string
            description:
              type: string
            terms:
              type: string
            defaultClientRoute:
              type: string
            isNSFW:
              type: boolean
            defaultNSFWPolicy:
              type: string
            customizations:
              type: object
              properties:
                javascript:
                  type: string
                css:
                  type: string
        theme:
          type: object
          properties:
            default:
              type: string
        services:
          type: object
          properties:
            twitter:
              type: object
              properties:
                username:
                  type: string
                whitelisted:
                  type: boolean
        cache:
          type: object
          properties:
            previews:
              type: object
              properties:
                size:
                  type: integer
            captions:
              type: object
              properties:
                size:
                  type: integer
        signup:
          type: object
          properties:
            enabled:
              type: boolean
            limit:
              type: integer
            requiresEmailVerification:
              type: boolean
        admin:
          type: object
          properties:
            email:
              type: string
              format: email
        contactForm:
          type: object
          properties:
            enabled:
              type: boolean
        user:
          type: object
          description: Settings that apply to new users, if registration is enabled
          properties:
            videoQuota:
              type: integer
              example: 16810141515
            videoQuotaDaily:
              type: integer
              example: 1681014151
        transcoding:
          type: object
          description: Settings pertaining to transcoding jobs
          properties:
            enabled:
              type: boolean
            allowAdditionalExtensions:
              type: boolean
              description: Allow your users to upload .mkv, .mov, .avi, .wmv, .flv, .f4v, .3g2, .3gp, .mts, m2ts, .mxf, .nut videos
            allowAudioFiles:
              type: boolean
              description: If a user uploads an audio file, PeerTube will create a video by merging the preview file and the audio file
            threads:
              type: integer
              description: Amount of threads used by ffmpeg for 1 transcoding job
            concurrency:
              type: number
              description: Amount of transcoding jobs to execute in parallel
            profile:
              type: string
              enum:
                - default
              description: |
                New profiles can be added by plugins ; available in core PeerTube: 'default'.
            resolutions:
              type: object
              description: Resolutions to transcode _new videos_ to
              properties:
                0p:
                  type: boolean
                144p:
                  type: boolean
                240p:
                  type: boolean
                360p:
                  type: boolean
                480p:
                  type: boolean
                720p:
                  type: boolean
                1080p:
                  type: boolean
                1440p:
                  type: boolean
                2160p:
                  type: boolean
            webtorrent:
              type: object
              description: WebTorrent-specific settings
              properties:
                enabled:
                  type: boolean
            hls:
              type: object
              description: HLS-specific settings
              properties:
                enabled:
                  type: boolean
        import:
          type: object
          properties:
            videos:
              type: object
              properties:
                http:
                  type: object
                  properties:
                    enabled:
                      type: boolean
                torrent:
                  type: object
                  properties:
                    enabled:
                      type: boolean
        autoBlacklist:
          type: object
          properties:
            videos:
              type: object
              properties:
                ofUsers:
                  type: object
                  properties:
                    enabled:
                      type: boolean
        followers:
          type: object
          properties:
            instance:
              type: object
              properties:
                enabled:
                  type: boolean
                manualApproval:
                  type: boolean

    CustomHomepage:
      properties:
        content:
          type: string

    Follow:
      properties:
        id:
          $ref: '#/components/schemas/id'
        follower:
          $ref: '#/components/schemas/Actor'
        following:
          $ref: '#/components/schemas/Actor'
        score:
          type: number
          description: score reflecting the reachability of the actor, with steps of `10` and a base score of `1000`.
        state:
          type: string
          enum:
            - pending
            - accepted
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    PredefinedAbuseReasons:
      description: Reason categories that help triage reports
      type: array
      maxItems: 8
      items:
        type: string
        enum:
        - violentOrAbusive
        - hatefulOrAbusive
        - spamOrMisleading
        - privacy
        - rights
        - serverRules
        - thumbnails
        - captions

    Job:
      properties:
        id:
          $ref: '#/components/schemas/id'
        state:
          type: string
          enum:
            - active
            - completed
            - failed
            - waiting
            - delayed
        type:
          type: string
          enum:
            - activitypub-http-unicast
            - activitypub-http-broadcast
            - activitypub-http-fetcher
            - activitypub-follow
            - video-file-import
            - video-transcoding
            - email
            - video-import
            - videos-views-stats
            - activitypub-refresher
            - video-redundancy
        data:
          type: object
          additionalProperties: true
        error:
          type: object
          additionalProperties: true
        createdAt:
          type: string
          format: date-time
        finishedOn:
          type: string
          format: date-time
        processedOn:
          type: string
          format: date-time
    AddUserResponse:
      properties:
        user:
          type: object
          properties:
            id:
              $ref: '#/components/schemas/id'
            account:
              type: object
              properties:
                id:
                  $ref: '#/components/schemas/id'
    VideoUploadRequestCommon:
      properties:
        name:
          description: Video name
          type: string
          example: What is PeerTube?
          minLength: 3
          maxLength: 120
        channelId:
          description: Channel id that will contain this video
          type: integer
          example: 3
          minimum: 1
        privacy:
          $ref: '#/components/schemas/VideoPrivacySet'
        category:
          $ref: '#/components/schemas/VideoCategorySet'
        licence:
          $ref: '#/components/schemas/VideoLicenceSet'
        language:
          $ref: '#/components/schemas/VideoLanguageSet'
        description:
          description: Video description
          type: string
          example: |
            **[Want to help to translate this video?](https://weblate.framasoft.org/projects/what-is-peertube-video/)**\r\n\r\n**Take back the control of your videos! [#JoinPeertube](https://joinpeertube.org)**
        waitTranscoding:
          description: Whether or not we wait transcoding before publish the video
          type: boolean
        support:
          description: A text tell the audience how to support the video creator
          example: Please support our work on https://soutenir.framasoft.org/en/ <3
          type: string
        nsfw:
          description: Whether or not this video contains sensitive content
          type: boolean
        tags:
          description: Video tags (maximum 5 tags each between 2 and 30 characters)
          type: array
          minItems: 1
          maxItems: 5
          uniqueItems: true
          example:
            - framasoft
            - peertube
          items:
            type: string
            minLength: 2
            maxLength: 30
        commentsEnabled:
          description: Enable or disable comments for this video
          type: boolean
        downloadEnabled:
          description: Enable or disable downloading for this video
          type: boolean
        originallyPublishedAt:
          description: Date when the content was originally published
          type: string
          format: date-time
        scheduleUpdate:
          $ref: '#/components/schemas/VideoScheduledUpdate'
        thumbnailfile:
          description: Video thumbnail file
          type: string
          format: binary
        previewfile:
          description: Video preview file
          type: string
          format: binary
      required:
        - channelId
        - name
    VideoUploadRequestLegacy:
      allOf:
        - $ref: '#/components/schemas/VideoUploadRequestCommon'
        - type: object
          required:
            - videofile
          properties:
            videofile:
              description: Video file
              type: string
              format: binary
    VideoUploadRequestResumable:
      allOf:
        - $ref: '#/components/schemas/VideoUploadRequestCommon'
        - type: object
          required:
            - filename
          properties:
            filename:
              description: Video filename including extension
              type: string
              format: filename
              example: what_is_peertube.mp4
            thumbnailfile:
              description: Video thumbnail file
              type: string
              format: binary
            previewfile:
              description: Video preview file
              type: string
              format: binary
    VideoUploadResponse:
      properties:
        video:
          type: object
          properties:
            id:
              $ref: '#/components/schemas/Video/properties/id'
            uuid:
              $ref: '#/components/schemas/Video/properties/uuid'
            shortUUID:
              $ref: '#/components/schemas/Video/properties/shortUUID'
    CommentThreadResponse:
      properties:
        total:
          type: integer
          example: 1
        data:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/VideoComment'
    CommentThreadPostResponse:
      properties:
        comment:
          $ref: '#/components/schemas/VideoComment'
    VideoListResponse:
      properties:
        total:
          type: integer
          example: 1
        data:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/Video'
    User:
      properties:
        account:
          $ref: '#/components/schemas/Account'
        autoPlayNextVideo:
          type: boolean
          description: Automatically start playing the upcoming video after the currently playing video
        autoPlayNextVideoPlaylist:
          type: boolean
          description: Automatically start playing the video on the playlist after the currently playing video
        autoPlayVideo:
          type: boolean
          description: Automatically start playing the video on the watch page
        blocked:
          type: boolean
        blockedReason:
          type: string
        createdAt:
          type: string
        email:
          type: string
          format: email
          description: The user email
        emailVerified:
          type: boolean
          description: Has the user confirmed their email address?
        id:
          allOf:
            - $ref: '#/components/schemas/id'
          readOnly: true
        pluginAuth:
          type: string
          description: Auth plugin to use to authenticate the user
        lastLoginDate:
          type: string
          format: date-time
        noInstanceConfigWarningModal:
          type: boolean
        noAccountSetupWarningModal:
          type: boolean
        noWelcomeModal:
          type: boolean
        nsfwPolicy:
          $ref: '#/components/schemas/NSFWPolicy'
        role:
          $ref: '#/components/schemas/UserRole'
        roleLabel:
          type: string
          enum:
            - User
            - Moderator
            - Administrator
        theme:
          type: string
          description: Theme enabled by this user
        username:
          $ref: '#/components/schemas/username'
        videoChannels:
          type: array
          items:
            $ref: '#/components/schemas/VideoChannel'
        videoQuota:
          type: integer
          description: The user video quota in bytes
          example: -1
        videoQuotaDaily:
          type: integer
          description: The user daily video quota in bytes
          example: -1
        p2pEnabled:
          type: boolean
          description: Enable P2P in the player
    UserWithStats:
      allOf:
        - $ref: '#/components/schemas/User'
        - properties:
            # optionally present fields: they require WITH_STATS scope
            videosCount:
              type: integer
              description: Count of videos published
            abusesCount:
              type: integer
              description: Count of reports/abuses of which the user is a target
            abusesAcceptedCount:
              type: integer
              description: Count of reports/abuses created by the user and accepted/acted upon by the moderation team
            abusesCreatedCount:
              type: integer
              description: Count of reports/abuses created by the user
            videoCommentsCount:
              type: integer
              description: Count of comments published
    AddUser:
      properties:
        username:
          $ref: '#/components/schemas/username'
        password:
          $ref: '#/components/schemas/password'
        email:
          type: string
          format: email
          description: The user email
        videoQuota:
          type: integer
          description: The user video quota in bytes
          example: -1
        videoQuotaDaily:
          type: integer
          description: The user daily video quota in bytes
          example: -1
        channelName:
          $ref: '#/components/schemas/usernameChannel'
        role:
          $ref: '#/components/schemas/UserRole'
        adminFlags:
          $ref: '#/components/schemas/UserAdminFlags'
      required:
        - username
        - password
        - email
        - videoQuota
        - videoQuotaDaily
        - role
    UpdateUser:
      properties:
        email:
          description: The updated email of the user
          allOf:
            - $ref: '#/components/schemas/User/properties/email'
        emailVerified:
          type: boolean
          description: Set the email as verified
        videoQuota:
          type: integer
          description: The updated video quota of the user in bytes
        videoQuotaDaily:
          type: integer
          description: The updated daily video quota of the user in bytes
        pluginAuth:
          type: string
          nullable: true
          description: The auth plugin to use to authenticate the user
          example: 'peertube-plugin-auth-saml2'
        role:
          $ref: '#/components/schemas/UserRole'
        adminFlags:
          $ref: '#/components/schemas/UserAdminFlags'
        password:
          $ref: '#/components/schemas/password'
    UpdateMe:
      # see shared/models/users/user-update-me.model.ts:
      properties:
        password:
          $ref: '#/components/schemas/password'
        currentPassword:
          $ref: '#/components/schemas/password'
        email:
          description: new email used for login and service communications
          allOf:
            - $ref: '#/components/schemas/User/properties/email'
        displayName:
          type: string
          description: new name of the user in its representations
          minLength: 3
          maxLength: 120
        displayNSFW:
          type: string
          description: new NSFW display policy
          enum:
            - 'true'
            - 'false'
            - both
        p2pEnabled:
          type: boolean
          description: whether to enable P2P in the player or not
        autoPlayVideo:
          type: boolean
          description: new preference regarding playing videos automatically
        autoPlayNextVideo:
          type: boolean
          description: new preference regarding playing following videos automatically
        autoPlayNextVideoPlaylist:
          type: boolean
          description: new preference regarding playing following playlist videos automatically
        videosHistoryEnabled:
          type: boolean
          description: whether to keep track of watched history or not
        videoLanguages:
          type: array
          items:
            type: string
          description: list of languages to filter videos down to
        theme:
          type: string
        noInstanceConfigWarningModal:
          type: boolean
        noAccountSetupWarningModal:
          type: boolean
        noWelcomeModal:
          type: boolean
    GetMeVideoRating:
      properties:
        id:
          $ref: '#/components/schemas/id'
        rating:
          type: string
          enum:
            - like
            - dislike
            - none
          description: Rating of the video
      required:
        - id
        - rating
    VideoRating:
      properties:
        video:
          $ref: '#/components/schemas/Video'
        rating:
          type: string
          enum:
            - like
            - dislike
            - none
          description: Rating of the video
      required:
        - video
        - rating
    RegisterUser:
      properties:
        username:
          description: immutable name of the user, used to find or mention its actor
          allOf:
            - $ref: '#/components/schemas/username'
        password:
          $ref: '#/components/schemas/password'
        email:
          type: string
          format: email
          description: email of the user, used for login or service communications
        displayName:
          type: string
          description: editable name of the user, displayed in its representations
          minLength: 1
          maxLength: 120
        channel:
          type: object
          description: channel base information used to create the first channel of the user
          properties:
            name:
              $ref: '#/components/schemas/usernameChannel'
            displayName:
              $ref: '#/components/schemas/VideoChannel/properties/displayName'
      required:
        - username
        - password
        - email

    OAuthClient:
      properties:
        client_id:
          type: string
          pattern: /^[a-z0-9]$/
          maxLength: 32
          minLength: 32
          example: v1ikx5hnfop4mdpnci8nsqh93c45rldf
        client_secret:
          type: string
          pattern: /^[a-zA-Z0-9]$/
          maxLength: 32
          minLength: 32
          example: AjWiOapPltI6EnsWQwlFarRtLh4u8tDt
    OAuthToken-password:
      allOf:
        - $ref: '#/components/schemas/OAuthClient'
        - type: object
          properties:
            grant_type:
              type: string
              enum:
                - password
                - refresh_token
              default: password
            username:
              $ref: '#/components/schemas/User/properties/username'
            password:
              $ref: '#/components/schemas/password'
      required:
        - client_id
        - client_secret
        - grant_type
        - username
        - password
    OAuthToken-refresh_token:
      allOf:
        - $ref: '#/components/schemas/OAuthClient'
        - type: object
          properties:
            grant_type:
              type: string
              enum:
                - password
                - refresh_token
              default: password
            refresh_token:
              type: string
              example: 2e0d675df9fc96d2e4ec8a3ebbbf45eca9137bb7
      required:
        - client_id
        - client_secret
        - grant_type
        - refresh_token

    VideoChannel:
      properties:
        # GET/POST/PUT properties
        displayName:
          type: string
          description: editable name of the channel, displayed in its representations
          example: Videos of Framasoft
          minLength: 1
          maxLength: 120
        description:
          type: string
          example: Videos made with <3 by Framasoft
          minLength: 3
          maxLength: 1000
        support:
          type: string
          description: text shown by default on all videos of this channel, to tell the audience how to support it
          example: Please support our work on https://soutenir.framasoft.org/en/ <3
          minLength: 3
          maxLength: 1000
        # GET-only properties
        id:
          readOnly: true
          allOf:
            - $ref: '#/components/schemas/id'
        isLocal:
          readOnly: true
          type: boolean
        updatedAt:
          readOnly: true
          type: string
          format: date-time
        ownerAccount:
          readOnly: true
          nullable: true
          type: object
          properties:
            id:
              type: integer
            uuid:
              $ref: '#/components/schemas/UUIDv4'
    VideoChannelCreate:
      allOf:
        - $ref: '#/components/schemas/VideoChannel'
        - properties:
            name:
              description: username of the channel to create
              allOf:
                - $ref: '#/components/schemas/usernameChannel'
      required:
        - name
        - displayName
    VideoChannelUpdate:
      allOf:
        - $ref: '#/components/schemas/VideoChannel'
        - properties:
            bulkVideosSupportUpdate:
              type: boolean
              description: Update the support field for all videos of this channel
    VideoChannelList:
      properties:
        total:
          type: integer
          example: 1
        data:
          type: array
          items:
            allOf:
              - $ref: '#/components/schemas/VideoChannel'
              - $ref: '#/components/schemas/Actor'

    MRSSPeerLink:
      type: object
      xml:
        name: 'media:peerLink'
      properties:
        href:
          type: string
          xml:
            attribute: true
        type:
          type: string
          enum:
            - application/x-bittorrent
          xml:
            attribute: true
    MRSSGroupContent:
      type: object
      xml:
        name: 'media:content'
      properties:
        url:
          type: string
          format: url
          xml:
            attribute: true
        fileSize:
          type: integer
          xml:
            attribute: true
        type:
          type: string
          xml:
            attribute: true
        framerate:
          type: integer
          xml:
            attribute: true
        duration:
          type: integer
          xml:
            attribute: true
        height:
          type: integer
          xml:
            attribute: true
        lang:
          type: string
          xml:
            attribute: true
    VideoCommentsForXML:
      type: array
      xml:
        wrapped: true
        name: 'channel'
      items:
        type: object
        xml:
          name: 'item'
        properties:
          link:
            type: string
            format: url
          guid:
            type: string
          pubDate:
            type: string
            format: date-time
          'content:encoded':
            type: string
          'dc:creator':
            type: string
    VideosForXML:
      type: array
      xml:
        wrapped: true
        name: 'channel'
      items:
        type: object
        xml:
          name: 'item'
        properties:
          link:
            type: string
            format: url
            description: video watch page URL
          guid:
            type: string
            description: video canonical URL
          pubDate:
            type: string
            format: date-time
            description: video publication date
          description:
            type: string
            description: video description
          'content:encoded':
            type: string
            description: video description
          'dc:creator':
            type: string
            description: publisher user name
          'media:category':
            type: integer
            description: video category (MRSS)
          'media:community':
            type: object
            description: see [media:community](https://www.rssboard.org/media-rss#media-community) (MRSS)
            properties:
              'media:statistics':
                type: object
                properties:
                  views:
                    type: integer
                    xml:
                      attribute: true
          'media:embed':
            type: object
            properties:
              url:
                type: string
                format: url
                description: video embed path, relative to the canonical URL domain (MRSS)
                xml:
                  attribute: true
          'media:player':
            type: object
            properties:
              url:
                type: string
                format: url
                description: video watch path, relative to the canonical URL domain (MRSS)
                xml:
                  attribute: true
          'media:thumbnail':
            type: object
            properties:
              url:
                type: string
                format: url
                xml:
                  attribute: true
              height:
                type: integer
                xml:
                  attribute: true
              width:
                type: integer
                xml:
                  attribute: true
          'media:title':
            type: string
            description: see [media:title](https://www.rssboard.org/media-rss#media-title) (MRSS). We only use `plain` titles.
          'media:description':
            type: string
          'media:rating':
            type: string
            enum:
              - nonadult
              - adult
            description: see [media:rating](https://www.rssboard.org/media-rss#media-rating) (MRSS)
          'enclosure':
            type: object
            description: main streamable file for the video
            properties:
              url:
                type: string
                format: url
                xml:
                  attribute: true
              type:
                type: string
                enum:
                  - application/x-bittorrent
                xml:
                  attribute: true
              length:
                type: integer
                xml:
                  attribute: true
          'media:group':
            type: array
            description: list of streamable files for the video. see [media:peerLink](https://www.rssboard.org/media-rss#media-peerlink) and [media:content](https://www.rssboard.org/media-rss#media-content) or  (MRSS)
            items:
              anyOf:
                - $ref: '#/components/schemas/MRSSPeerLink'
                - $ref: '#/components/schemas/MRSSGroupContent'
    NotificationSettingValue:
      type: integer
      description: >
        Notification type

        - `0` NONE

        - `1` WEB

        - `2` EMAIL
      enum:
        - 0
        - 1
        - 2
    Notification:
      properties:
        id:
          $ref: '#/components/schemas/id'
        type:
          type: integer
          description: >
            Notification type, following the `UserNotificationType` enum:

            - `1` NEW_VIDEO_FROM_SUBSCRIPTION

            - `2` NEW_COMMENT_ON_MY_VIDEO

            - `3` NEW_ABUSE_FOR_MODERATORS

            - `4` BLACKLIST_ON_MY_VIDEO

            - `5` UNBLACKLIST_ON_MY_VIDEO

            - `6` MY_VIDEO_PUBLISHED

            - `7` MY_VIDEO_IMPORT_SUCCESS

            - `8` MY_VIDEO_IMPORT_ERROR

            - `9` NEW_USER_REGISTRATION

            - `10` NEW_FOLLOW

            - `11` COMMENT_MENTION

            - `12` VIDEO_AUTO_BLACKLIST_FOR_MODERATORS

            - `13` NEW_INSTANCE_FOLLOWER

            - `14` AUTO_INSTANCE_FOLLOWING

            - `15` ABUSE_STATE_CHANGE

            - `16` ABUSE_NEW_MESSAGE

            - `17` NEW_PLUGIN_VERSION

            - `18` NEW_PEERTUBE_VERSION
        read:
          type: boolean
        video:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/VideoInfo'
            - type: object
              properties:
                channel:
                  $ref: '#/components/schemas/ActorInfo'
        videoImport:
          nullable: true
          type: object
          properties:
            id:
              $ref: '#/components/schemas/id'
            video:
              nullable: true
              $ref: '#/components/schemas/VideoInfo'
            torrentName:
              type: string
              nullable: true
            magnetUri:
              $ref: '#/components/schemas/VideoImport/properties/magnetUri'
            targetUri:
              type: string
              format: uri
              nullable: true
        comment:
          nullable: true
          type: object
          properties:
            id:
              $ref: '#/components/schemas/id'
            threadId:
              type: integer
            video:
              $ref: '#/components/schemas/VideoInfo'
            account:
              $ref: '#/components/schemas/ActorInfo'
        videoAbuse:
          nullable: true
          type: object
          properties:
            id:
              $ref: '#/components/schemas/id'
            video:
              allOf:
                - $ref: '#/components/schemas/VideoInfo'
        videoBlacklist:
          nullable: true
          type: object
          properties:
            id:
              $ref: '#/components/schemas/id'
            video:
              allOf:
                - $ref: '#/components/schemas/VideoInfo'
        account:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ActorInfo'
        actorFollow:
          type: object
          nullable: true
          properties:
            id:
              $ref: '#/components/schemas/id'
            follower:
              $ref: '#/components/schemas/ActorInfo'
            state:
              type: string
              enum:
                - pending
                - accepted
            following:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - account
                    - channel
                    - instance
                name:
                  type: string
                displayName:
                  type: string
                host:
                  type: string
                  format: hostname
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    NotificationListResponse:
      properties:
        total:
          type: integer
          example: 1
        data:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/Notification'
    Plugin:
      properties:
        name:
          type: string
          example: peertube-plugin-auth-ldap
        type:
          type: integer
          description: >
            - `1`: PLUGIN

            - `2`: THEME
          enum:
            - 1
            - 2
        latestVersion:
          type: string
          example: 0.0.3
        version:
          type: string
          example: 0.0.1
        enabled:
          type: boolean
        uninstalled:
          type: boolean
        peertubeEngine:
          type: string
          example: 2.2.0
        description:
          type: string
        homepage:
          type: string
          format: url
          example: https://framagit.org/framasoft/peertube/official-plugins/tree/master/peertube-plugin-auth-ldap
        settings:
          type: object
          additionalProperties: true
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    PluginResponse:
      properties:
        total:
          type: integer
          example: 1
        data:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/Plugin'

    LiveVideoUpdate:
      properties:
        saveReplay:
          type: boolean
        permanentLive:
          description: User can stream multiple times in a permanent live
          type: boolean

    LiveVideoResponse:
      properties:
        rtmpUrl:
          type: string
        rtmpsUrl:
          type: string
        streamKey:
          type: string
          description: RTMP stream key to use to stream into this live video
        saveReplay:
          type: boolean
        permanentLive:
          description: User can stream multiple times in a permanent live
          type: boolean



  callbacks:
    searchIndex:
      'https://search.example.org/api/v1/search/videos':
        post:
          summary: third-party search index MAY be used instead of the local index, if enabled by the instance admin. see `searchTarget`
          responses:
            '200':
              description: successful operation
              content:
                application/json:
                  schema:
                    $ref: '#/components/schemas/VideoListResponse'
